import { db } from '../config/database.js';
import { users } from '../db/schema.js';
import { eq } from 'drizzle-orm';
import { hashPassword, generateTempPassword } from '../utils/password.js';
import { logUserCreation, logRoleChange } from '../services/audit.service.js';
import { formatErrorResponse, ConflictError, NotFoundError } from '../utils/errors.js';
import * as emailAccountService from '../services/email-account.service.js';

/**
 * Vytvorenie nového usera s automatic temporary password (admin only)
 * Ak je poskytnutý email a emailPassword, automaticky sa fetchne JMAP account ID
 * POST /api/admin/users
 */
export const createUser = async (req, res) => {
  const { username, email, emailPassword, firstName, lastName } = req.body;
  const adminId = req.userId;
  const ipAddress = req.ip || req.connection.remoteAddress;
  const userAgent = req.headers['user-agent'];

  try {
    // Skontroluj či username už neexistuje
    const [existingUser] = await db
      .select()
      .from(users)
      .where(eq(users.username, username))
      .limit(1);

    if (existingUser) {
      throw new ConflictError('Username už existuje');
    }

    // Automaticky vygeneruj temporary password
    const tempPassword = generateTempPassword(12);
    const hashedTempPassword = await hashPassword(tempPassword);

    // Vytvor usera
    const [newUser] = await db
      .insert(users)
      .values({
        username,
        tempPassword: hashedTempPassword,
        role: 'member', // Vždy member, nie admin
        firstName: firstName || null,
        lastName: lastName || null,
        changedPassword: false,
      })
      .returning();

    // Ak sú poskytnuté email credentials, vytvor email account (many-to-many)
    let emailAccountCreated = false;
    let emailAccountData = null;

    if (email && emailPassword) {
      try {
        // Použij emailAccountService ktorý automaticky vytvorí many-to-many link
        const newEmailAccount = await emailAccountService.createEmailAccount(
          newUser.id,
          email,
          emailPassword
        );

        emailAccountCreated = true;
        emailAccountData = {
          id: newEmailAccount.id,
          email: newEmailAccount.email,
          jmapAccountId: newEmailAccount.jmapAccountId,
          shared: newEmailAccount.shared,
        };
      } catch (emailError) {
        // Email account sa nepodarilo vytvoriť, ale user bol vytvorený
        // Admin môže pridať email account neskôr
        console.error('Failed to create email account:', emailError);
      }
    }

    // Log user creation
    await logUserCreation(adminId, newUser.id, username, 'member', ipAddress, userAgent);

    res.status(201).json({
      success: true,
      data: {
        user: {
          id: newUser.id,
          username: newUser.username,
          firstName: newUser.firstName,
          lastName: newUser.lastName,
          role: newUser.role,
          emailSetup: emailAccountCreated,
          emailAccount: emailAccountData,
          tempPassword: tempPassword, // Vráti plain text password pre admina aby ho mohol poslať userovi
        },
      },
      message: emailAccountCreated
        ? emailAccountData.shared
          ? 'Používateľ vytvorený a pripojený k existujúcemu zdieľanému email účtu.'
          : 'Používateľ úspešne vytvorený s novým emailovým účtom.'
        : 'Používateľ úspešne vytvorený. Email môže byť nastavený neskôr.',
    });
  } catch (error) {
    const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
    res.status(error.statusCode || 500).json(errorResponse);
  }
};

/**
 * Zoznam všetkých userov (admin only)
 * GET /api/admin/users
 */
export const getAllUsers = async (req, res) => {
  try {
    const allUsers = await db
      .select({
        id: users.id,
        username: users.username,
        firstName: users.firstName,
        lastName: users.lastName,
        role: users.role,
        changedPassword: users.changedPassword,
        lastLogin: users.lastLogin,
        createdAt: users.createdAt,
      })
      .from(users);

    res.status(200).json({
      success: true,
      count: allUsers.length,
      data: allUsers,
    });
  } catch (error) {
    const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
    res.status(error.statusCode || 500).json(errorResponse);
  }
};

/**
 * Získanie konkrétneho usera (admin only)
 * GET /api/admin/users/:userId
 */
export const getUser = async (req, res) => {
  const { userId } = req.params;

  try {
    const [user] = await db
      .select({
        id: users.id,
        username: users.username,
        firstName: users.firstName,
        lastName: users.lastName,
        role: users.role,
        changedPassword: users.changedPassword,
        lastLogin: users.lastLogin,
        createdAt: users.createdAt,
        updatedAt: users.updatedAt,
      })
      .from(users)
      .where(eq(users.id, userId))
      .limit(1);

    if (!user) {
      throw new NotFoundError('Používateľ nenájdený');
    }

    // Get user's email accounts (cez many-to-many)
    const userEmailAccounts = await emailAccountService.getUserEmailAccounts(userId);

    res.status(200).json({
      success: true,
      data: {
        user: {
          ...user,
          emailAccounts: userEmailAccounts,
        },
      },
    });
  } catch (error) {
    const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
    res.status(error.statusCode || 500).json(errorResponse);
  }
};

/**
 * Zmena role usera (admin only)
 * PATCH /api/admin/users/:userId/role
 */
export const changeUserRole = async (req, res) => {
  const { userId } = req.params;
  const { role } = req.body;
  const adminId = req.userId;
  const ipAddress = req.ip || req.connection.remoteAddress;
  const userAgent = req.headers['user-agent'];

  try {
    // Získaj starú rolu
    const [user] = await db
      .select()
      .from(users)
      .where(eq(users.id, userId))
      .limit(1);

    if (!user) {
      throw new NotFoundError('Používateľ nenájdený');
    }

    const oldRole = user.role;

    // Update role
    await db
      .update(users)
      .set({
        role,
        updatedAt: new Date(),
      })
      .where(eq(users.id, userId));

    // Log role change
    await logRoleChange(adminId, userId, oldRole, role, ipAddress, userAgent);

    res.status(200).json({
      success: true,
      data: {
        userId,
        oldRole,
        newRole: role,
      },
      message: 'Rola používateľa bola zmenená',
    });
  } catch (error) {
    const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
    res.status(error.statusCode || 500).json(errorResponse);
  }
};

/**
 * Zmazanie usera (admin only)
 * DELETE /api/admin/users/:userId
 */
export const deleteUser = async (req, res) => {
  const { userId } = req.params;

  try {
    const [user] = await db
      .select()
      .from(users)
      .where(eq(users.id, userId))
      .limit(1);

    if (!user) {
      throw new NotFoundError('Používateľ nenájdený');
    }

    // Zabraň zmazaniu posledného admina
    if (user.role === 'admin') {
      const [adminCount] = await db
        .select({ count: db.$count(users) })
        .from(users)
        .where(eq(users.role, 'admin'));

      if (adminCount.count <= 1) {
        throw new ConflictError('Nemôžete zmazať posledného administrátora');
      }
    }

    await db.delete(users).where(eq(users.id, userId));

    res.status(200).json({
      success: true,
      message: 'Používateľ bol zmazaný',
    });
  } catch (error) {
    const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
    res.status(error.statusCode || 500).json(errorResponse);
  }
};
