import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Param,
  Body,
  UseGuards,
  NotFoundException,
  ConflictException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { RolesGuard, Roles } from '@it0/common';
import { User } from '../../../domain/entities/user.entity';
import * as bcrypt from 'bcryptjs';
import * as crypto from 'crypto';

@Controller('api/v1/auth/users')
@UseGuards(RolesGuard)
@Roles('platform_admin', 'platform_super_admin')
export class UserController {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
  ) {}

  @Get()
  async listUsers() {
    const users = await this.userRepository.find({
      order: { createdAt: 'DESC' },
    });

    const data = users.map((u) => ({
      id: u.id,
      displayName: u.name,
      email: u.email,
      role: u.roles?.[0] ?? 'viewer',
      tenantId: u.tenantId,
      tenantName: u.tenantId,
      status: u.isActive ? 'active' : 'disabled',
      lastLoginAt: u.lastLoginAt?.toISOString() ?? null,
      createdAt: u.createdAt.toISOString(),
    }));

    return { data, total: data.length };
  }

  @Get(':id')
  async getUser(@Param('id') id: string) {
    const user = await this.userRepository.findOne({ where: { id } });
    if (!user) throw new NotFoundException(`User "${id}" not found`);

    return {
      id: user.id,
      displayName: user.name,
      email: user.email,
      role: user.roles?.[0] ?? 'viewer',
      tenantId: user.tenantId,
      tenantName: user.tenantId,
      status: user.isActive ? 'active' : 'disabled',
      lastLoginAt: user.lastLoginAt?.toISOString() ?? null,
      createdAt: user.createdAt.toISOString(),
    };
  }

  @Post()
  async createUser(
    @Body()
    body: {
      displayName: string;
      email: string;
      password: string;
      role?: string;
      tenantId?: string;
    },
  ) {
    const existing = await this.userRepository.findOne({
      where: { email: body.email },
    });
    if (existing) throw new ConflictException('Email already registered');

    const passwordHash = await bcrypt.hash(body.password, 12);

    const user = this.userRepository.create({
      id: crypto.randomUUID(),
      tenantId: body.tenantId || 'default',
      email: body.email,
      passwordHash,
      name: body.displayName,
      roles: [body.role || 'viewer'],
      isActive: true,
    });

    const saved = await this.userRepository.save(user);

    return {
      id: saved.id,
      displayName: saved.name,
      email: saved.email,
      role: saved.roles?.[0] ?? 'viewer',
      tenantId: saved.tenantId,
      status: 'active',
      createdAt: saved.createdAt.toISOString(),
    };
  }

  @Put(':id')
  async updateUser(
    @Param('id') id: string,
    @Body() body: { role?: string; status?: string },
  ) {
    const user = await this.userRepository.findOne({ where: { id } });
    if (!user) throw new NotFoundException(`User "${id}" not found`);

    if (body.role) user.roles = [body.role];
    if (body.status) user.isActive = body.status === 'active';

    const saved = await this.userRepository.save(user);

    return {
      id: saved.id,
      displayName: saved.name,
      email: saved.email,
      role: saved.roles?.[0] ?? 'viewer',
      tenantId: saved.tenantId,
      status: saved.isActive ? 'active' : 'disabled',
    };
  }

  @Delete(':id')
  @Roles('platform_super_admin')
  async deleteUser(@Param('id') id: string) {
    const user = await this.userRepository.findOne({ where: { id } });
    if (!user) throw new NotFoundException(`User "${id}" not found`);
    await this.userRepository.remove(user);
    return { success: true };
  }
}
