import { Injectable } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';

export interface CurrentUser {
  id: string;
  name?: string;
  username?: string;
  roleId: string;
  email?: string;
}

export interface AuthenticatedRequest {
  headers?: Record<string, string | string[] | undefined>;
  currentUser?: CurrentUser | null;
}

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

  async resolveCurrentUser(request: AuthenticatedRequest): Promise<CurrentUser | null> {
    if (request.currentUser !== undefined) return request.currentUser;

    const userId = headerValue(request, 'x-ftb-user-id') || headerValue(request, 'x-user-id');
    if (!userId) {
      request.currentUser = null;
      return null;
    }

    const headerUser: CurrentUser = {
      id: userId,
      name: decodeHeader(headerValue(request, 'x-ftb-user-name')),
      username: headerValue(request, 'x-ftb-user-username'),
      roleId: headerValue(request, 'x-ftb-user-role-id') || '',
      email: headerValue(request, 'x-ftb-user-email'),
    };

    if (headerUser.roleId) {
      request.currentUser = headerUser;
      return headerUser;
    }

    const row = await this.prisma.user.findUnique({
      where: { id: userId },
      select: { id: true, name: true, username: true, roleId: true, email: true },
    });
    request.currentUser = row ? {
      id: row.id,
      name: row.name,
      username: row.username ?? undefined,
      roleId: row.roleId || 'member',
      email: row.email,
    } : null;
    return request.currentUser;
  }
}

function headerValue(request: AuthenticatedRequest, name: string): string {
  const value = request.headers?.[name] ?? request.headers?.[name.toLowerCase()];
  if (Array.isArray(value)) return value[0] ?? '';
  return value ?? '';
}

function decodeHeader(value: string): string {
  try {
    return decodeURIComponent(value);
  } catch {
    return value;
  }
}
