import { NextRequest, NextResponse } from 'next/server';
import { db, schema } from '@/lib/db';
import { eq, and, isNull } from 'drizzle-orm';
import bcrypt from 'bcrypt';
import { createCompanyUserSchema } from '@/lib/validators';
import { getSession } from '@/lib/auth';
import { isCompanyOwner, canAddUserToCompany } from '@/lib/companies';
import { z } from 'zod';

/**
 * GET /api/companies/[id]/users
 * List all users in the company
 * - Owner: full access to all users
 * - Regular user: limited access (can see other users but limited data)
 */
export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id } = await params;

    // Verify authentication
    const accessToken = request.cookies.get('scriba.access_token')?.value;
    const sessionData = await getSession(accessToken);

    if (!sessionData) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    const { user } = sessionData;

    // Verify user belongs to this company
    if (user.companyId !== id) {
      return NextResponse.json(
        { error: 'Access denied. You are not a member of this company.' },
        { status: 403 }
      );
    }

    // Check if user is owner
    const isOwner = await isCompanyOwner(user.id, id);

    // Get users
    const users = await db.query.users.findMany({
      where: eq(schema.users.companyId, id),
      columns: isOwner
        ? {
            // Owner sees everything
            id: true,
            email: true,
            name: true,
            role: true,
            isOwner: true,
            emailVerified: true,
            twoFactorEnabled: true,
            createdAt: true,
            updatedAt: true,
          }
        : {
            // Regular users see limited info
            id: true,
            name: true,
            role: true,
            isOwner: true,
          },
      orderBy: (users, { desc }) => [desc(users.createdAt)],
    });

    const availableUsers = isOwner
      ? await db.query.users.findMany({
          where: and(
            isNull(schema.users.companyId),
            eq(schema.users.isOwner, false),
            eq(schema.users.role, 'client')
          ),
          columns: {
            id: true,
            email: true,
            name: true,
            role: true,
            emailVerified: true,
            createdAt: true,
          },
          orderBy: (users, { desc }) => [desc(users.createdAt)],
        })
      : [];

    return NextResponse.json({
      users,
      availableUsers,
      count: users.length,
      isOwner,
    });

  } catch (error) {
    console.error('List company users error:', error);
    return NextResponse.json(
      { error: 'Failed to retrieve users' },
      { status: 500 }
    );
  }
}

/**
 * POST /api/companies/[id]/users
 * Create a new user in the company
 * - Owner only: can create users
 * - Respects company user limit based on package
 * - New user is automatically linked to the company
 */
export async function POST(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id } = await params;

    // Verify authentication
    const accessToken = request.cookies.get('scriba.access_token')?.value;
    const sessionData = await getSession(accessToken);

    if (!sessionData) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    const { user: currentUser } = sessionData;

    // Verify user belongs to this company
    if (currentUser.companyId !== id) {
      return NextResponse.json(
        { error: 'Access denied. You are not a member of this company.' },
        { status: 403 }
      );
    }

    // Verify ownership - only owner can create users
    const isOwner = await isCompanyOwner(currentUser.id, id);
    if (!isOwner) {
      return NextResponse.json(
        { error: 'Only the company owner can create new users' },
        { status: 403 }
      );
    }

    // Check if we can add more users
    const canAdd = await canAddUserToCompany(id);
    if (!canAdd.allowed) {
      return NextResponse.json(
        { error: canAdd.reason },
        { status: 400 }
      );
    }

    // Parse and validate request body
    const body = await request.json();
    const existingUserLinkSchema = z.object({
      existingUserId: z.string().min(1, 'User is required'),
      role: z.enum(['client', 'admin']).optional(),
    });

    const existingUserLink = existingUserLinkSchema.safeParse(body);
    if (existingUserLink.success) {
      const { existingUserId, role } = existingUserLink.data;

      const existingUser = await db.query.users.findFirst({
        where: eq(schema.users.id, existingUserId),
      });

      if (!existingUser) {
        return NextResponse.json({ error: 'User not found' }, { status: 404 });
      }

      if (existingUser.isOwner) {
        return NextResponse.json(
          { error: 'Cannot attach a company owner to another company' },
          { status: 400 }
        );
      }

      if (existingUser.role === 'admin') {
        return NextResponse.json(
          { error: 'Admin users cannot be assigned through company members' },
          { status: 400 }
        );
      }

      if (existingUser.companyId === id) {
        return NextResponse.json(
          { error: 'User already belongs to this company' },
          { status: 400 }
        );
      }

      if (existingUser.companyId) {
        return NextResponse.json(
          { error: 'User already belongs to another company' },
          { status: 400 }
        );
      }

      const [updatedUser] = await db
        .update(schema.users)
        .set({
          companyId: id,
          isOwner: false,
          role: role ?? existingUser.role,
          updatedAt: new Date(),
        })
        .where(eq(schema.users.id, existingUserId))
        .returning();

      return NextResponse.json({
        success: true,
        user: {
          id: updatedUser.id,
          email: updatedUser.email,
          name: updatedUser.name,
          role: updatedUser.role,
          isOwner: updatedUser.isOwner,
          companyId: updatedUser.companyId,
        },
        message: 'User added to company successfully',
      });
    }

    const parsed = createCompanyUserSchema.safeParse(body);

    if (!parsed.success) {
      return NextResponse.json(
        { error: parsed.error.issues[0]?.message ?? 'Invalid input' },
        { status: 400 }
      );
    }

    const { email, password, name, role } = parsed.data;

    // Check if user with this email already exists
    const existingUser = await db.query.users.findFirst({
      where: eq(schema.users.email, email),
    });

    if (existingUser) {
      // If user exists but is not in this company
      if (existingUser.companyId !== id) {
        return NextResponse.json(
          { error: 'A user with this email already exists in another company' },
          { status: 400 }
        );
      }
      return NextResponse.json(
        { error: 'A user with this email already exists in this company' },
        { status: 400 }
      );
    }

    // Hash password
    const hashedPassword = await bcrypt.hash(password, 10);

    // Create user
    const userId = crypto.randomUUID();
    const [newUser] = await db
      .insert(schema.users)
      .values({
        id: userId,
        email,
        name: name || email.split('@')[0],
        companyId: id,
        isOwner: false, // New users are never owners
        role,
        emailVerified: true, // Owner-created users are pre-verified
      })
      .returning();

    // Create account with password
    await db.insert(schema.accounts).values({
      id: crypto.randomUUID(),
      userId,
      accountId: email,
      providerId: 'credential',
      password: hashedPassword,
    });

    return NextResponse.json({
      success: true,
      user: {
        id: newUser.id,
        email: newUser.email,
        name: newUser.name,
        role: newUser.role,
        isOwner: newUser.isOwner,
        companyId: newUser.companyId,
      },
      message: 'User created successfully',
    });

  } catch (error) {
    console.error('Create company user error:', error);
    return NextResponse.json(
      { error: 'Failed to create user' },
      { status: 500 }
    );
  }
}

/**
 * DELETE /api/companies/[id]/users?userId=xxx
 * Remove a user from the company
 * - Owner only: can remove users
 * - Cannot remove the owner themselves
 * - User's companyId is set to null (user becomes unassigned)
 */
export async function DELETE(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id: companyId } = await params;

    // Verify authentication
    const accessToken = request.cookies.get('scriba.access_token')?.value;
    const sessionData = await getSession(accessToken);

    if (!sessionData) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    const { user: currentUser } = sessionData;

    // Verify user belongs to this company
    if (currentUser.companyId !== companyId) {
      return NextResponse.json(
        { error: 'Access denied. You are not a member of this company.' },
        { status: 403 }
      );
    }

    // Verify ownership - only owner can remove users
    const isOwner = await isCompanyOwner(currentUser.id, companyId);
    if (!isOwner) {
      return NextResponse.json(
        { error: 'Only the company owner can remove users' },
        { status: 403 }
      );
    }

    // Get target user ID from query params
    const { searchParams } = new URL(request.url);
    const userId = searchParams.get('userId');

    if (!userId) {
      return NextResponse.json(
        { error: 'User ID is required' },
        { status: 400 }
      );
    }

    // Find the target user
    const targetUser = await db.query.users.findFirst({
      where: eq(schema.users.id, userId),
    });

    if (!targetUser) {
      return NextResponse.json(
        { error: 'User not found' },
        { status: 404 }
      );
    }

    // Verify target user belongs to this company
    if (targetUser.companyId !== companyId) {
      return NextResponse.json(
        { error: 'User does not belong to this company' },
        { status: 403 }
      );
    }

    // Prevent removing the owner
    if (targetUser.isOwner) {
      return NextResponse.json(
        { error: 'Cannot remove the company owner. Transfer ownership first.' },
        { status: 400 }
      );
    }

    // Prevent self-removal (owner shouldn't remove themselves this way)
    if (targetUser.id === currentUser.id) {
      return NextResponse.json(
        { error: 'Use company transfer instead to leave the company' },
        { status: 400 }
      );
    }

    // Remove user from company (set companyId to null)
    await db
      .update(schema.users)
      .set({
        companyId: null,
        isOwner: false,
      })
      .where(eq(schema.users.id, userId));

    return NextResponse.json({
      success: true,
      message: 'User removed from company successfully',
    });

  } catch (error) {
    console.error('Remove company user error:', error);
    return NextResponse.json(
      { error: 'Failed to remove user' },
      { status: 500 }
    );
  }
}
