import { pinyin } from 'pinyin-pro';

export interface Department {
  id: string;
  name: string;
  parentId?: string;
  order: number;
  createdAt: string;
}

export interface Member {
  id: string;
  name: string;
  username?: string;
  departmentId: string;
  roleId: string;
  phone: string;
  email: string;
  password: string;
  createdAt: string;
  isSystem?: boolean;
}

export interface RoleItem {
  id: string;
  name: string;
  description?: string;
  createdAt: string;
  isSystem?: boolean;
  permissions: string[];
}

export interface PasswordRule {
  prefix: string;
  length: number;
  includeUppercase: boolean;
  includeLowercase: boolean;
  includeNumbers: boolean;
  includeSpecial: boolean;
}

export const DEFAULT_PASSWORD_RULE: PasswordRule = {
  prefix: 'Ftb',
  length: 8,
  includeUppercase: true,
  includeLowercase: true,
  includeNumbers: true,
  includeSpecial: false,
};

export function generatePassword(rule: PasswordRule): string {
  let chars = '';
  if (rule.includeUppercase) chars += 'ABCDEFGHJKLMNPQRSTUVWXYZ';
  if (rule.includeLowercase) chars += 'abcdefghjkmnpqrstuvwxyz';
  if (rule.includeNumbers) chars += '23456789';
  if (rule.includeSpecial) chars += '!@#$%&*';
  if (!chars) chars = 'abcdefghjkmnpqrstuvwxyz23456789';

  const randomLength = Math.max(rule.length - rule.prefix.length, 4);
  let result = rule.prefix;
  for (let i = 0; i < randomLength; i++) {
    result += chars[Math.floor(Math.random() * chars.length)];
  }
  return result;
}

export function maskPhone(phone: string): string {
  if (!phone || phone.length < 7) return phone;
  return phone.slice(0, 3) + '****' + phone.slice(7);
}

export function normalizeUsername(username: string | undefined | null): string {
  return (username ?? '').trim().replace(/\s+/g, '').toLowerCase();
}

function nameToUsernameBase(name: string): string {
  const raw = name.trim();
  if (!raw) return 'USER';
  const letters = pinyin(raw, { toneType: 'none', type: 'array' })
    .join('')
    .replace(/[^a-zA-Z0-9]/g, '')
    .toLowerCase();
  return letters || 'USER';
}

function duplicateSuffix(attempt: number): string {
  return attempt === 1 ? '1' : `${'0'.repeat(attempt - 1)}1`;
}

function uniqueUsernameFromBase(base: string, existingUsernames: Iterable<string>): string {
  const normalizedBase = normalizeUsername(base) || 'USER';
  const used = new Set(Array.from(existingUsernames, normalizeUsername).filter(Boolean));
  if (!used.has(normalizedBase)) return normalizedBase;

  for (let attempt = 1; attempt < 1000; attempt += 1) {
    const candidate = `${normalizedBase}${duplicateSuffix(attempt)}`;
    if (!used.has(candidate)) return candidate;
  }

  return `${normalizedBase}${Date.now()}`;
}

export function generateUsernameFromName(
  name: string,
  existingUsernames: Iterable<string>,
  currentUsername?: string,
): string {
  const normalizedCurrent = normalizeUsername(currentUsername);
  if (normalizedCurrent) return normalizedCurrent;
  return uniqueUsernameFromBase(nameToUsernameBase(name), existingUsernames);
}

export function ensureMemberUsernames(members: Member[]): { members: Member[]; changed: boolean } {
  const used = new Set<string>();
  let changed = false;
  const normalizedMembers = members.map((member) => {
    const requested = normalizeUsername(member.username);
    const username = requested
      ? uniqueUsernameFromBase(requested, used)
      : generateUsernameFromName(member.name, used);

    used.add(username);
    if (member.username === username) return member;
    changed = true;
    return { ...member, username };
  });

  return { members: normalizedMembers, changed };
}
