import {
  Controller,
  Get,
  Put,
  Post,
  Delete,
  Param,
  Body,
  Req,
  UseGuards,
  NotFoundException,
} 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 { ApiKey } from '../../../domain/entities/api-key.entity';
import * as bcrypt from 'bcryptjs';
import * as crypto from 'crypto';

@Controller('api/v1/admin/settings')
@UseGuards(RolesGuard)
@Roles('admin', 'platform_admin', 'platform_super_admin')
export class SettingsController {
  // In-memory store for platform settings (would be a DB table in production)
  private generalSettings: Record<string, any> = {
    platformName: 'IT0',
    defaultTimezone: 'UTC',
    defaultLanguage: 'en',
    autoApproveThreshold: 1,
  };

  private notificationSettings: Record<string, any> = {
    emailEnabled: false,
    smsEnabled: false,
    pushEnabled: true,
    defaultEscalationPolicy: 'immediate',
  };

  private themeSettings: Record<string, any> = {
    mode: 'dark',
    primaryColor: '#3b82f6',
  };

  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    @InjectRepository(ApiKey)
    private readonly apiKeyRepository: Repository<ApiKey>,
  ) {}

  // --- General Settings ---

  @Get('general')
  async getGeneral() {
    return this.generalSettings;
  }

  @Put('general')
  async updateGeneral(@Body() body: any) {
    Object.assign(this.generalSettings, body);
    return this.generalSettings;
  }

  // --- Notification Settings ---

  @Get('notifications')
  async getNotifications() {
    return this.notificationSettings;
  }

  @Put('notifications')
  async updateNotifications(@Body() body: any) {
    Object.assign(this.notificationSettings, body);
    return this.notificationSettings;
  }

  // --- API Keys ---

  @Get('api-keys')
  async listApiKeys(@Req() req: any) {
    const userId = req.user?.sub || req.user?.id;
    const keys = await this.apiKeyRepository.find({
      where: userId ? { userId } : {},
      order: { createdAt: 'DESC' },
    });

    return keys.map((k) => ({
      id: k.id,
      name: k.name,
      key: '****' + k.keyHash.slice(-8),
      createdAt: k.createdAt.toISOString(),
      lastUsedAt: k.lastUsedAt?.toISOString() ?? null,
    }));
  }

  @Post('api-keys')
  async createApiKey(@Req() req: any, @Body() body: { name: string }) {
    const userId = req.user?.sub || req.user?.id;
    const tenantId = req.user?.tenantId || 'default';
    const rawKey = `it0_${crypto.randomBytes(32).toString('hex')}`;
    const keyHash = await bcrypt.hash(rawKey, 10);

    const apiKey = this.apiKeyRepository.create({
      id: crypto.randomUUID(),
      tenantId,
      userId,
      keyHash,
      name: body.name,
      permissions: [],
      isActive: true,
    });

    await this.apiKeyRepository.save(apiKey);
    return { key: rawKey };
  }

  @Delete('api-keys/:id')
  async deleteApiKey(@Param('id') id: string) {
    const key = await this.apiKeyRepository.findOne({ where: { id } });
    if (!key) throw new NotFoundException(`API key "${id}" not found`);
    await this.apiKeyRepository.remove(key);
    return { success: true };
  }

  // --- Theme Settings ---

  @Get('theme')
  async getTheme() {
    return this.themeSettings;
  }

  @Put('theme')
  async updateTheme(@Body() body: any) {
    Object.assign(this.themeSettings, body);
    return this.themeSettings;
  }

  // --- Account Settings ---

  @Get('account')
  async getAccount(@Req() req: any) {
    const userId = req.user?.sub || req.user?.id;
    if (!userId) return { displayName: 'Admin', email: '' };

    const user = await this.userRepository.findOne({ where: { id: userId } });
    if (!user) return { displayName: 'Admin', email: '' };

    return {
      displayName: user.name,
      email: user.email,
    };
  }

  @Put('account')
  async updateAccount(@Req() req: any, @Body() body: { displayName: string }) {
    const userId = req.user?.sub || req.user?.id;
    if (!userId) throw new NotFoundException('User not found');

    const user = await this.userRepository.findOne({ where: { id: userId } });
    if (!user) throw new NotFoundException('User not found');

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

    return { displayName: saved.name, email: saved.email };
  }

  @Put('account/password')
  async changePassword(
    @Req() req: any,
    @Body() body: { currentPassword: string; newPassword: string },
  ) {
    const userId = req.user?.sub || req.user?.id;
    if (!userId) throw new NotFoundException('User not found');

    const user = await this.userRepository.findOne({ where: { id: userId } });
    if (!user) throw new NotFoundException('User not found');

    const valid = await bcrypt.compare(body.currentPassword, user.passwordHash);
    if (!valid) {
      return { success: false, message: 'Current password is incorrect' };
    }

    user.passwordHash = await bcrypt.hash(body.newPassword, 12);
    await this.userRepository.save(user);

    return { success: true };
  }
}
