import { BadRequestException, Injectable } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { CreateMemberDto } from './dto/create-member.dto';
import { UpdateMemberDto } from './dto/update-member.dto';

const SYSTEM_ADMIN_MEMBER_ID = 'm-8';
const SYSTEM_ADMIN_NAME = '超级管理员';
const SYSTEM_ADMIN_USERNAME = 'admin';
const SYSTEM_ADMIN_ROLE_ID = 'role-admin';

@Injectable()
export class MemberService {
  constructor(private readonly prisma: PrismaService) {}

  async findAll() {
    const rows = await (this.prisma.user as any).findMany({ orderBy: [{ isSystem: 'desc' }, { name: 'asc' }] });
    return rows.map(toMember);
  }

  async create(dto: CreateMemberDto) {
    const data = toUserData(dto);
    const row = await (this.prisma.user as any).create({ data });
    return toMember(row);
  }

  async update(id: string, dto: UpdateMemberDto) {
    const data = id === SYSTEM_ADMIN_MEMBER_ID
      ? { ...sanitizeSystemAdminPatch(dto), isSystem: true }
      : toUserData(dto, { partial: true });
    const row = await (this.prisma.user as any).update({ where: { id }, data });
    return toMember(row);
  }

  async remove(id: string) {
    if (id === SYSTEM_ADMIN_MEMBER_ID) {
      throw new BadRequestException('系统内置超级管理员不可删除');
    }
    await (this.prisma.user as any).delete({ where: { id } });
    return { deleted: true };
  }
}

function sanitizeSystemAdminPatch(dto: UpdateMemberDto) {
  const data = toUserData(dto, { partial: true });
  delete (data as any).name;
  delete (data as any).username;
  delete (data as any).departmentId;
  delete (data as any).roleId;
  delete (data as any).email;
  return data;
}

function toUserData(dto: Partial<CreateMemberDto>, options: { partial?: boolean } = {}) {
  const id = (dto as any).id as string | undefined;
  const email = dto.email?.trim() || (options.partial ? undefined : `${id || dto.username || Date.now()}@local.ftb`);
  return {
    ...(id !== undefined && { id }),
    ...(dto.name !== undefined && { name: dto.name }),
    ...(dto.username !== undefined && { username: emptyToNull(dto.username) }),
    ...(dto.departmentId !== undefined && { departmentId: emptyToNull(dto.departmentId) }),
    ...(dto.roleId !== undefined && { roleId: dto.roleId || 'member' }),
    ...(dto.phone !== undefined && { phone: dto.phone ?? '' }),
    ...(email !== undefined && { email }),
    ...(dto.password !== undefined && { password: dto.password ?? '' }),
    ...(dto.isSystem !== undefined && { isSystem: dto.isSystem }),
  };
}

function toMember(row: any) {
  return {
    id: row.id,
    name: row.id === SYSTEM_ADMIN_MEMBER_ID ? SYSTEM_ADMIN_NAME : row.name,
    username: row.id === SYSTEM_ADMIN_MEMBER_ID ? SYSTEM_ADMIN_USERNAME : row.username ?? undefined,
    departmentId: row.id === SYSTEM_ADMIN_MEMBER_ID ? '' : row.departmentId ?? '',
    roleId: row.id === SYSTEM_ADMIN_MEMBER_ID ? SYSTEM_ADMIN_ROLE_ID : row.roleId ?? 'member',
    phone: row.phone ?? '',
    email: row.email?.endsWith('@local.ftb') ? '' : row.email ?? '',
    password: row.password ?? '',
    createdAt: toIsoDate(row.createdAt),
    isSystem: Boolean(row.isSystem) || row.id === SYSTEM_ADMIN_MEMBER_ID,
  };
}

function emptyToNull(value: string | null | undefined): string | null {
  if (value === null) return null;
  if (value === undefined) return null;
  const trimmed = value.trim();
  return trimmed ? trimmed : null;
}

function toIsoDate(value: unknown): string {
  if (value instanceof Date) return value.toISOString().slice(0, 10);
  if (typeof value === 'string' && value) return value.slice(0, 10);
  return new Date().toISOString().slice(0, 10);
}
