import db from '../config/database';
import { logger } from '../utils/logger';
import * as crypto from 'crypto';
import * as jwt from 'jsonwebtoken';

export interface LoginInput {
  tenantId: string;
  shopId: string;
  taskId: string;
  traceId: string;
  businessType: 'TOC' | 'TOB';
  username: string;
  password: string;
  rememberMe?: boolean;
}

export interface LoginResult {
  success: boolean;
  userId?: string;
  username?: string;
  email?: string;
  role?: string;
  token?: string;
  refreshToken?: string;
  expiresAt?: Date;
  permissions?: string[];
  error?: string;
}

export interface RegisterInput {
  tenantId: string;
  shopId: string;
  taskId: string;
  traceId: string;
  businessType: 'TOC' | 'TOB';
  username: string;
  email: string;
  password: string;
  role?: string;
}

export interface RegisterResult {
  success: boolean;
  userId?: string;
  error?: string;
}

export interface PasswordResetInput {
  tenantId: string;
  shopId: string;
  taskId: string;
  traceId: string;
  businessType: 'TOC' | 'TOB';
  email: string;
}

export interface PasswordResetResult {
  success: boolean;
  resetToken?: string;
  expiresAt?: Date;
  error?: string;
}

export interface PermissionCheckInput {
  tenantId: string;
  shopId: string;
  taskId: string;
  traceId: string;
  businessType: 'TOC' | 'TOB';
  userId: string;
  permission: string;
}

export interface PermissionCheckResult {
  hasPermission: boolean;
  userId: string;
  permission: string;
}

export interface UserPermissionsInput {
  tenantId: string;
  shopId: string;
  taskId: string;
  traceId: string;
  businessType: 'TOC' | 'TOB';
  userId: string;
}

export interface UserPermissionsResult {
  userId: string;
  role: string;
  permissions: string[];
  rolePermissions: string[];
  customPermissions: string[];
}

export interface AssignRoleInput {
  tenantId: string;
  shopId: string;
  taskId: string;
  traceId: string;
  businessType: 'TOC' | 'TOB';
  userId: string;
  role: string;
  assignedBy: string;
}

export interface AssignRoleResult {
  success: boolean;
  userId: string;
  previousRole?: string;
  newRole: string;
  assignedAt: Date;
}

export interface SessionValidationInput {
  tenantId: string;
  shopId: string;
  taskId: string;
  traceId: string;
  businessType: 'TOC' | 'TOB';
  token: string;
}

export interface SessionValidationResult {
  valid: boolean;
  userId?: string;
  username?: string;
  role?: string;
  expiresAt?: Date;
  sessionId?: string;
  error?: string;
}

export interface RefreshTokenInput {
  tenantId: string;
  shopId: string;
  taskId: string;
  traceId: string;
  businessType: 'TOC' | 'TOB';
  refreshToken: string;
}

export interface RefreshTokenResult {
  success: boolean;
  token?: string;
  refreshToken?: string;
  expiresAt?: Date;
  error?: string;
}

export interface LogoutInput {
  tenantId: string;
  shopId: string;
  taskId: string;
  traceId: string;
  businessType: 'TOC' | 'TOB';
  token: string;
}

export interface LogoutResult {
  success: boolean;
  sessionId?: string;
  loggedOutAt?: Date;
}

export interface SessionInfo {
  sessionId: string;
  userId: string;
  username: string;
  ipAddress?: string;
  userAgent?: string;
  createdAt: Date;
  expiresAt: Date;
  lastActivityAt: Date;
}

export class AuthService {
  private static readonly JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
  private static readonly JWT_EXPIRES_IN = '24h';
  private static readonly REFRESH_TOKEN_EXPIRES_IN = '7d';

  static async login(input: LoginInput): Promise<LoginResult> {
    const { tenantId, shopId, taskId, traceId, businessType, username, password, rememberMe } = input;

    logger.info(`[AuthService] Login attempt - username: ${username}, tenantId: ${tenantId}, traceId: ${traceId}`);

    try {
      const user = await db('cf_users')
        .where({ username, tenant_id: tenantId, status: 'ACTIVE' })
        .first();

      if (!user) {
        logger.warn(`[AuthService] Login failed - user not found: ${username}`);
        return { success: false, error: 'Invalid username or password' };
      }

      const passwordHash = this.hashPassword(password, user.salt);
      if (passwordHash !== user.password_hash) {
        logger.warn(`[AuthService] Login failed - invalid password: ${username}`);
        return { success: false, error: 'Invalid username or password' };
      }

      const permissions = await this.getUserPermissions(user.id);

      const token = jwt.sign(
        { userId: user.id, username: user.username, role: user.role, tenantId, shopId },
        this.JWT_SECRET,
        { expiresIn: rememberMe ? '7d' : this.JWT_EXPIRES_IN }
      );

      const refreshToken = jwt.sign(
        { userId: user.id, type: 'refresh' },
        this.JWT_SECRET,
        { expiresIn: this.REFRESH_TOKEN_EXPIRES_IN }
      );

      const expiresAt = new Date();
      expiresAt.setHours(expiresAt.getHours() + (rememberMe ? 168 : 24));

      const sessionId = `SESS-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
      await db('cf_sessions').insert({
        id: sessionId,
        user_id: user.id,
        tenant_id: tenantId,
        shop_id: shopId,
        task_id: taskId,
        trace_id: traceId,
        business_type: businessType,
        token,
        refresh_token: refreshToken,
        expires_at: expiresAt,
        created_at: new Date(),
        last_activity_at: new Date(),
      });

      await db('cf_users')
        .where({ id: user.id })
        .update({ last_login_at: new Date() });

      logger.info(`[AuthService] Login successful - userId: ${user.id}, sessionId: ${sessionId}`);

      return {
        success: true,
        userId: user.id,
        username: user.username,
        email: user.email,
        role: user.role,
        token,
        refreshToken,
        expiresAt,
        permissions,
      };
    } catch (error: any) {
      logger.error(`[AuthService] Login error - username: ${username}, error: ${error.message}`);
      return { success: false, error: 'Authentication failed' };
    }
  }

  static async register(input: RegisterInput): Promise<RegisterResult> {
    const { tenantId, shopId, taskId, traceId, businessType, username, email, password, role = 'OPERATOR' } = input;

    logger.info(`[AuthService] Register attempt - username: ${username}, email: ${email}, tenantId: ${tenantId}, traceId: ${traceId}`);

    try {
      const existingUser = await db('cf_users')
        .where({ tenant_id: tenantId })
        .andWhere(function() {
          this.where({ username }).orWhere({ email });
        })
        .first();

      if (existingUser) {
        logger.warn(`[AuthService] Register failed - user already exists: ${username}`);
        return { success: false, error: 'Username or email already exists' };
      }

      const userId = `USER-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
      const salt = crypto.randomBytes(16).toString('hex');
      const passwordHash = this.hashPassword(password, salt);

      await db('cf_users').insert({
        id: userId,
        tenant_id: tenantId,
        shop_id: shopId,
        task_id: taskId,
        trace_id: traceId,
        business_type: businessType,
        username,
        email,
        password_hash: passwordHash,
        salt,
        role,
        status: 'ACTIVE',
        created_at: new Date(),
        updated_at: new Date(),
      });

      logger.info(`[AuthService] Register successful - userId: ${userId}`);

      return { success: true, userId };
    } catch (error: any) {
      logger.error(`[AuthService] Register error - username: ${username}, error: ${error.message}`);
      return { success: false, error: 'Registration failed' };
    }
  }

  static async requestPasswordReset(input: PasswordResetInput): Promise<PasswordResetResult> {
    const { tenantId, shopId, taskId, traceId, businessType, email } = input;

    logger.info(`[AuthService] Password reset request - email: ${email}, tenantId: ${tenantId}, traceId: ${traceId}`);

    try {
      const user = await db('cf_users')
        .where({ email, tenant_id: tenantId, status: 'ACTIVE' })
        .first();

      if (!user) {
        logger.warn(`[AuthService] Password reset failed - user not found: ${email}`);
        return { success: false, error: 'User not found' };
      }

      const resetToken = crypto.randomBytes(32).toString('hex');
      const expiresAt = new Date();
      expiresAt.setHours(expiresAt.getHours() + 1);

      await db('cf_password_resets').insert({
        id: `PR-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
        user_id: user.id,
        tenant_id: tenantId,
        shop_id: shopId,
        task_id: taskId,
        trace_id: traceId,
        business_type: businessType,
        reset_token: resetToken,
        expires_at: expiresAt,
        used: false,
        created_at: new Date(),
      });

      logger.info(`[AuthService] Password reset token generated - userId: ${user.id}`);

      return { success: true, resetToken, expiresAt };
    } catch (error: any) {
      logger.error(`[AuthService] Password reset error - email: ${email}, error: ${error.message}`);
      return { success: false, error: 'Password reset failed' };
    }
  }

  static async checkPermission(input: PermissionCheckInput): Promise<PermissionCheckResult> {
    const { tenantId, shopId, taskId, traceId, businessType, userId, permission } = input;

    logger.info(`[AuthService] Permission check - userId: ${userId}, permission: ${permission}, traceId: ${traceId}`);

    try {
      const user = await db('cf_users')
        .where({ id: userId, tenant_id: tenantId, status: 'ACTIVE' })
        .first();

      if (!user) {
        return { hasPermission: false, userId, permission };
      }

      const rolePermissions = await this.getRolePermissions(user.role);
      const customPermissions = await this.getUserCustomPermissions(userId);

      const allPermissions = [...new Set([...rolePermissions, ...customPermissions])];
      const hasPermission = allPermissions.includes(permission) || allPermissions.includes('*');

      logger.info(`[AuthService] Permission check result - userId: ${userId}, permission: ${permission}, hasPermission: ${hasPermission}`);

      return { hasPermission, userId, permission };
    } catch (error: any) {
      logger.error(`[AuthService] Permission check error - userId: ${userId}, error: ${error.message}`);
      return { hasPermission: false, userId, permission };
    }
  }

  static async getUserPermissionsList(input: UserPermissionsInput): Promise<UserPermissionsResult> {
    const { tenantId, shopId, taskId, traceId, businessType, userId } = input;

    logger.info(`[AuthService] Get user permissions - userId: ${userId}, traceId: ${traceId}`);

    try {
      const user = await db('cf_users')
        .where({ id: userId, tenant_id: tenantId, status: 'ACTIVE' })
        .first();

      if (!user) {
        throw new Error('User not found');
      }

      const rolePermissions = await this.getRolePermissions(user.role);
      const customPermissions = await this.getUserCustomPermissions(userId);

      const allPermissions = [...new Set([...rolePermissions, ...customPermissions])];

      return {
        userId,
        role: user.role,
        permissions: allPermissions,
        rolePermissions,
        customPermissions,
      };
    } catch (error: any) {
      logger.error(`[AuthService] Get user permissions error - userId: ${userId}, error: ${error.message}`);
      throw error;
    }
  }

  static async assignRole(input: AssignRoleInput): Promise<AssignRoleResult> {
    const { tenantId, shopId, taskId, traceId, businessType, userId, role, assignedBy } = input;

    logger.info(`[AuthService] Assign role - userId: ${userId}, role: ${role}, assignedBy: ${assignedBy}, traceId: ${traceId}`);

    try {
      const user = await db('cf_users')
        .where({ id: userId, tenant_id: tenantId, status: 'ACTIVE' })
        .first();

      if (!user) {
        throw new Error('User not found');
      }

      const previousRole = user.role;
      const assignedAt = new Date();

      await db('cf_users')
        .where({ id: userId })
        .update({ role, updated_at: assignedAt });

      await db('cf_role_assignments').insert({
        id: `RA-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
        user_id: userId,
        tenant_id: tenantId,
        shop_id: shopId,
        task_id: taskId,
        trace_id: traceId,
        business_type: businessType,
        previous_role: previousRole,
        new_role: role,
        assigned_by: assignedBy,
        assigned_at: assignedAt,
      });

      logger.info(`[AuthService] Role assigned - userId: ${userId}, previousRole: ${previousRole}, newRole: ${role}`);

      return {
        success: true,
        userId,
        previousRole,
        newRole: role,
        assignedAt,
      };
    } catch (error: any) {
      logger.error(`[AuthService] Assign role error - userId: ${userId}, error: ${error.message}`);
      throw error;
    }
  }

  static async validateSession(input: SessionValidationInput): Promise<SessionValidationResult> {
    const { tenantId, shopId, taskId, traceId, businessType, token } = input;

    logger.info(`[AuthService] Validate session - traceId: ${traceId}`);

    try {
      const decoded = jwt.verify(token, this.JWT_SECRET) as any;

      const session = await db('cf_sessions')
        .where({ token, tenant_id: tenantId, status: 'ACTIVE' })
        .first();

      if (!session) {
        return { valid: false, error: 'Session not found' };
      }

      if (new Date() > new Date(session.expires_at)) {
        await db('cf_sessions')
          .where({ id: session.id })
          .update({ status: 'EXPIRED' });
        return { valid: false, error: 'Session expired' };
      }

      await db('cf_sessions')
        .where({ id: session.id })
        .update({ last_activity_at: new Date() });

      return {
        valid: true,
        userId: decoded.userId,
        username: decoded.username,
        role: decoded.role,
        expiresAt: new Date(session.expires_at),
        sessionId: session.id,
      };
    } catch (error: any) {
      logger.error(`[AuthService] Validate session error - error: ${error.message}`);
      return { valid: false, error: 'Invalid token' };
    }
  }

  static async refreshToken(input: RefreshTokenInput): Promise<RefreshTokenResult> {
    const { tenantId, shopId, taskId, traceId, businessType, refreshToken } = input;

    logger.info(`[AuthService] Refresh token - traceId: ${traceId}`);

    try {
      const decoded = jwt.verify(refreshToken, this.JWT_SECRET) as any;

      if (decoded.type !== 'refresh') {
        return { success: false, error: 'Invalid refresh token' };
      }

      const session = await db('cf_sessions')
        .where({ refresh_token: refreshToken, tenant_id: tenantId, status: 'ACTIVE' })
        .first();

      if (!session) {
        return { success: false, error: 'Session not found' };
      }

      const user = await db('cf_users')
        .where({ id: decoded.userId, status: 'ACTIVE' })
        .first();

      if (!user) {
        return { success: false, error: 'User not found' };
      }

      const newToken = jwt.sign(
        { userId: user.id, username: user.username, role: user.role, tenantId, shopId },
        this.JWT_SECRET,
        { expiresIn: this.JWT_EXPIRES_IN }
      );

      const newRefreshToken = jwt.sign(
        { userId: user.id, type: 'refresh' },
        this.JWT_SECRET,
        { expiresIn: this.REFRESH_TOKEN_EXPIRES_IN }
      );

      const expiresAt = new Date();
      expiresAt.setHours(expiresAt.getHours() + 24);

      await db('cf_sessions')
        .where({ id: session.id })
        .update({
          token: newToken,
          refresh_token: newRefreshToken,
          expires_at: expiresAt,
          last_activity_at: new Date(),
        });

      logger.info(`[AuthService] Token refreshed - userId: ${user.id}, sessionId: ${session.id}`);

      return {
        success: true,
        token: newToken,
        refreshToken: newRefreshToken,
        expiresAt,
      };
    } catch (error: any) {
      logger.error(`[AuthService] Refresh token error - error: ${error.message}`);
      return { success: false, error: 'Token refresh failed' };
    }
  }

  static async logout(input: LogoutInput): Promise<LogoutResult> {
    const { tenantId, shopId, taskId, traceId, businessType, token } = input;

    logger.info(`[AuthService] Logout - traceId: ${traceId}`);

    try {
      const session = await db('cf_sessions')
        .where({ token, tenant_id: tenantId })
        .first();

      if (!session) {
        return { success: false };
      }

      const loggedOutAt = new Date();

      await db('cf_sessions')
        .where({ id: session.id })
        .update({ status: 'LOGGED_OUT', logged_out_at: loggedOutAt });

      logger.info(`[AuthService] Logout successful - sessionId: ${session.id}`);

      return {
        success: true,
        sessionId: session.id,
        loggedOutAt,
      };
    } catch (error: any) {
      logger.error(`[AuthService] Logout error - error: ${error.message}`);
      return { success: false };
    }
  }

  static async getActiveSessions(userId: string, tenantId: string): Promise<SessionInfo[]> {
    const sessions = await db('cf_sessions')
      .join('cf_users', 'cf_sessions.user_id', 'cf_users.id')
      .where({
        'cf_sessions.user_id': userId,
        'cf_sessions.tenant_id': tenantId,
        'cf_sessions.status': 'ACTIVE',
      })
      .where('cf_sessions.expires_at', '>', new Date())
      .select(
        'cf_sessions.id as sessionId',
        'cf_sessions.user_id as userId',
        'cf_users.username',
        'cf_sessions.ip_address',
        'cf_sessions.user_agent',
        'cf_sessions.created_at as createdAt',
        'cf_sessions.expires_at as expiresAt',
        'cf_sessions.last_activity_at as lastActivityAt'
      );

    return sessions.map((s: any) => ({
      sessionId: s.sessionId,
      userId: s.userId,
      username: s.username,
      ipAddress: s.ip_address,
      userAgent: s.user_agent,
      createdAt: new Date(s.createdAt),
      expiresAt: new Date(s.expiresAt),
      lastActivityAt: new Date(s.lastActivityAt),
    }));
  }

  private static hashPassword(password: string, salt: string): string {
    return crypto.pbkdf2Sync(password, salt, 10000, 64, 'sha512').toString('hex');
  }

  private static async getUserPermissions(userId: string): Promise<string[]> {
    const user = await db('cf_users').where({ id: userId }).first();
    if (!user) return [];

    const rolePermissions = await this.getRolePermissions(user.role);
    const customPermissions = await this.getUserCustomPermissions(userId);

    return [...new Set([...rolePermissions, ...customPermissions])];
  }

  private static async getRolePermissions(role: string): Promise<string[]> {
    const roleData = await db('cf_roles').where({ name: role }).first();
    if (!roleData || !roleData.permissions) return [];

    try {
      return JSON.parse(roleData.permissions);
    } catch {
      return [];
    }
  }

  private static async getUserCustomPermissions(userId: string): Promise<string[]> {
    const permissions = await db('cf_user_permissions')
      .where({ user_id: userId, granted: true })
      .select('permission');

    return permissions.map((p: any) => p.permission);
  }

  static async initializeTables(): Promise<void> {
    if (!(await db.schema.hasTable('cf_users'))) {
      await db.schema.createTable('cf_users', (table) => {
        table.string('id').primary();
        table.string('tenant_id').notNullable();
        table.string('shop_id').notNullable();
        table.string('task_id').notNullable();
        table.string('trace_id').notNullable();
        table.enum('business_type', ['TOC', 'TOB']).notNullable();
        table.string('username').notNullable();
        table.string('email').notNullable();
        table.string('password_hash').notNullable();
        table.string('salt').notNullable();
        table.enum('role', ['ADMIN', 'MANAGER', 'OPERATOR', 'FINANCE', 'SOURCING', 'LOGISTICS', 'ANALYST']).defaultTo('OPERATOR');
        table.enum('status', ['ACTIVE', 'INACTIVE', 'SUSPENDED']).defaultTo('ACTIVE');
        table.timestamp('last_login_at');
        table.timestamp('created_at').defaultTo(db.fn.now());
        table.timestamp('updated_at').defaultTo(db.fn.now());

        table.unique(['tenant_id', 'username']);
        table.unique(['tenant_id', 'email']);
        table.index(['tenant_id', 'shop_id']);
        table.index(['status']);
      });
      logger.info('[AuthService] Created cf_users table');
    }

    if (!(await db.schema.hasTable('cf_sessions'))) {
      await db.schema.createTable('cf_sessions', (table) => {
        table.string('id').primary();
        table.string('user_id').notNullable();
        table.string('tenant_id').notNullable();
        table.string('shop_id').notNullable();
        table.string('task_id').notNullable();
        table.string('trace_id').notNullable();
        table.enum('business_type', ['TOC', 'TOB']).notNullable();
        table.text('token').notNullable();
        table.text('refresh_token').notNullable();
        table.timestamp('expires_at').notNullable();
        table.timestamp('created_at').defaultTo(db.fn.now());
        table.timestamp('last_activity_at').defaultTo(db.fn.now());
        table.timestamp('logged_out_at');
        table.enum('status', ['ACTIVE', 'EXPIRED', 'LOGGED_OUT']).defaultTo('ACTIVE');
        table.string('ip_address');
        table.text('user_agent');

        table.foreign('user_id').references('cf_users.id');
        table.index(['user_id']);
        table.index(['tenant_id', 'shop_id']);
        table.index(['status']);
        table.index(['token']);
      });
      logger.info('[AuthService] Created cf_sessions table');
    }

    if (!(await db.schema.hasTable('cf_roles'))) {
      await db.schema.createTable('cf_roles', (table) => {
        table.string('id').primary();
        table.string('tenant_id').notNullable();
        table.string('name').notNullable();
        table.text('description');
        table.json('permissions');
        table.timestamp('created_at').defaultTo(db.fn.now());
        table.timestamp('updated_at').defaultTo(db.fn.now());

        table.unique(['tenant_id', 'name']);
        table.index(['tenant_id']);
      });
      logger.info('[AuthService] Created cf_roles table');
    }

    if (!(await db.schema.hasTable('cf_user_permissions'))) {
      await db.schema.createTable('cf_user_permissions', (table) => {
        table.string('id').primary();
        table.string('user_id').notNullable();
        table.string('permission').notNullable();
        table.boolean('granted').defaultTo(true);
        table.timestamp('created_at').defaultTo(db.fn.now());

        table.foreign('user_id').references('cf_users.id');
        table.unique(['user_id', 'permission']);
        table.index(['user_id']);
      });
      logger.info('[AuthService] Created cf_user_permissions table');
    }

    if (!(await db.schema.hasTable('cf_role_assignments'))) {
      await db.schema.createTable('cf_role_assignments', (table) => {
        table.string('id').primary();
        table.string('user_id').notNullable();
        table.string('tenant_id').notNullable();
        table.string('shop_id').notNullable();
        table.string('task_id').notNullable();
        table.string('trace_id').notNullable();
        table.enum('business_type', ['TOC', 'TOB']).notNullable();
        table.string('previous_role');
        table.string('new_role').notNullable();
        table.string('assigned_by').notNullable();
        table.timestamp('assigned_at').defaultTo(db.fn.now());

        table.foreign('user_id').references('cf_users.id');
        table.index(['user_id']);
        table.index(['tenant_id', 'shop_id']);
      });
      logger.info('[AuthService] Created cf_role_assignments table');
    }

    if (!(await db.schema.hasTable('cf_password_resets'))) {
      await db.schema.createTable('cf_password_resets', (table) => {
        table.string('id').primary();
        table.string('user_id').notNullable();
        table.string('tenant_id').notNullable();
        table.string('shop_id').notNullable();
        table.string('task_id').notNullable();
        table.string('trace_id').notNullable();
        table.enum('business_type', ['TOC', 'TOB']).notNullable();
        table.string('reset_token').notNullable();
        table.timestamp('expires_at').notNullable();
        table.boolean('used').defaultTo(false);
        table.timestamp('created_at').defaultTo(db.fn.now());

        table.foreign('user_id').references('cf_users.id');
        table.index(['user_id']);
        table.index(['reset_token']);
        table.index(['tenant_id', 'shop_id']);
      });
      logger.info('[AuthService] Created cf_password_resets table');
    }

    await this.seedDefaultRoles();
  }

  private static async seedDefaultRoles(): Promise<void> {
    const defaultRoles = [
      {
        name: 'ADMIN',
        description: 'System administrator with full access',
        permissions: JSON.stringify(['*']),
      },
      {
        name: 'MANAGER',
        description: 'Operations manager',
        permissions: JSON.stringify([
          'user:read', 'user:write',
          'product:read', 'product:write',
          'order:read', 'order:write',
          'report:read',
        ]),
      },
      {
        name: 'OPERATOR',
        description: 'Operations specialist',
        permissions: JSON.stringify([
          'product:read', 'product:write',
          'order:read', 'order:write',
        ]),
      },
      {
        name: 'FINANCE',
        description: 'Finance manager',
        permissions: JSON.stringify([
          'finance:read', 'finance:write',
          'report:read',
          'order:read',
        ]),
      },
      {
        name: 'SOURCING',
        description: 'Sourcing specialist',
        permissions: JSON.stringify([
          'product:read', 'product:write',
          'supplier:read', 'supplier:write',
        ]),
      },
      {
        name: 'LOGISTICS',
        description: 'Logistics specialist',
        permissions: JSON.stringify([
          'order:read',
          'logistics:read', 'logistics:write',
          'tracking:read',
        ]),
      },
      {
        name: 'ANALYST',
        description: 'Data analyst',
        permissions: JSON.stringify([
          'report:read',
          'analytics:read',
          'product:read',
          'order:read',
        ]),
      },
    ];

    for (const role of defaultRoles) {
      const exists = await db('cf_roles').where({ name: role.name }).first();
      if (!exists) {
        await db('cf_roles').insert({
          id: `ROLE-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
          tenant_id: 'SYSTEM',
          ...role,
        });
      }
    }
  }

  /**
   * 初始化数据库表
   */
  static async initTable() {
    await this.initializeTables();
  }

  /**
   * 验证JWT令牌
   */
  static verifyToken(token: string): any {
    try {
      const decoded = jwt.verify(token, this.JWT_SECRET) as any;
      return decoded;
    } catch (error) {
      return null;
    }
  }
}
