import { NextRequest, NextResponse } from 'next/server';
import { db, schema } from '@/lib/db';
import { eq } from 'drizzle-orm';
import { getSession } from '@/lib/auth';
import { canAddUserToCompany } from '@/lib/companies';

// GET /api/admin/users/[id] - Get single user (admin only)
export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id } = await params;
    const accessToken = request.cookies.get('scriba.access_token')?.value;
    const session = await getSession(accessToken);

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

    // Check if user is admin
    const currentUser = await db.query.users.findFirst({
      where: eq(schema.users.id, session.user.id)
    });

    if (!currentUser || currentUser.role !== 'admin') {
      return NextResponse.json({ error: 'Forbidden - Admin access required' }, { status: 403 });
    }

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

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

    const effectiveTier = user.companyId
      ? await db.query.companies.findFirst({
          where: eq(schema.companies.id, user.companyId),
          columns: { package: true },
        }).then((company) => company?.package ?? user.tier)
      : user.tier;

    return NextResponse.json({ user: { ...user, tier: effectiveTier } });
  } catch (error) {
    console.error('Error fetching user:', error);
    return NextResponse.json({ error: 'Failed to fetch user' }, { status: 500 });
  }
}

// PUT /api/admin/users/[id] - Update user (admin only)
export async function PUT(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id } = await params;
    const accessToken = request.cookies.get('scriba.access_token')?.value;
    const session = await getSession(accessToken);

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

    // Check if user is admin
    const currentUser = await db.query.users.findFirst({
      where: eq(schema.users.id, session.user.id)
    });

    if (!currentUser || currentUser.role !== 'admin') {
      return NextResponse.json({ error: 'Forbidden - Admin access required' }, { status: 403 });
    }

    const body = await request.json();
    const { email, name, role, emailVerified, password } = body;
    const normalizedCompanyId =
      body.companyId === undefined
        ? undefined
        : (body.companyId === '' || body.companyId === null ? null : String(body.companyId));

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

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

    const nextRole = role ?? existingUser.role;
    const nextCompanyId = normalizedCompanyId !== undefined ? normalizedCompanyId : existingUser.companyId;

    // Non-admin users must always belong to a company.
    if (nextRole !== 'admin' && !nextCompanyId) {
      return NextResponse.json(
        { error: 'Company is required for non-admin users' },
        { status: 400 }
      );
    }

    // Owner assignment changes must go through dedicated owner transfer flow.
    if (existingUser.isOwner && normalizedCompanyId !== undefined && normalizedCompanyId !== existingUser.companyId) {
      return NextResponse.json(
        { error: 'Cannot move a company owner. Transfer ownership first.' },
        { status: 400 }
      );
    }

    let nextCompanyPackage: string | null = null;
    if (nextCompanyId) {
      const company = await db.query.companies.findFirst({
        where: eq(schema.companies.id, nextCompanyId),
      });
      if (!company) {
        return NextResponse.json({ error: 'Company not found' }, { status: 404 });
      }
      nextCompanyPackage = company.package;

      const isMovingToNewCompany = nextCompanyId !== existingUser.companyId;
      if (isMovingToNewCompany && !existingUser.isOwner) {
        const canAdd = await canAddUserToCompany(nextCompanyId);
        if (!canAdd.allowed) {
          return NextResponse.json({ error: canAdd.reason }, { status: 400 });
        }
      }
    }

    // Build update object
    const updateData: any = {
      updatedAt: new Date()
    };

    if (email !== undefined) updateData.email = email;
    if (name !== undefined) updateData.name = name;
    if (role !== undefined) updateData.role = role;
    if (emailVerified !== undefined) updateData.emailVerified = emailVerified;
    if (normalizedCompanyId !== undefined) updateData.companyId = normalizedCompanyId;
    updateData.tier = nextCompanyPackage ?? 'starter';

    // Update user
    const updatedUser = await db.update(schema.users)
      .set(updateData)
      .where(eq(schema.users.id, id))
      .returning();

    // Update password if provided
    if (password) {
      const bcrypt = await import('bcrypt');
      const hashedPassword = await bcrypt.hash(password, 10);
      
      // Check if credential account exists
      const existingAccount = await db.query.accounts.findFirst({
        where: eq(schema.accounts.userId, id)
      });

      if (existingAccount) {
        await db.update(schema.accounts)
          .set({ password: hashedPassword })
          .where(eq(schema.accounts.userId, id));
      } else {
        await db.insert(schema.accounts).values({
          id: crypto.randomUUID(),
          userId: id,
          accountId: updatedUser[0].email,
          providerId: 'credential',
          password: hashedPassword
        });
      }
    }

    return NextResponse.json({ success: true, user: updatedUser[0] });
  } catch (error) {
    console.error('Error updating user:', error);
    return NextResponse.json({ error: 'Failed to update user' }, { status: 500 });
  }
}

// DELETE /api/admin/users/[id] - Delete user (admin only)
export async function DELETE(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id } = await params;
    const accessToken = request.cookies.get('scriba.access_token')?.value;
    const session = await getSession(accessToken);

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

    // Check if user is admin
    const currentUser = await db.query.users.findFirst({
      where: eq(schema.users.id, session.user.id)
    });

    if (!currentUser || currentUser.role !== 'admin') {
      return NextResponse.json({ error: 'Forbidden - Admin access required' }, { status: 403 });
    }

    // Prevent deleting yourself
    if (id === session.user.id) {
      return NextResponse.json({ error: 'Cannot delete yourself' }, { status: 400 });
    }

    const deletedUser = await db.delete(schema.users)
      .where(eq(schema.users.id, id))
      .returning();

    if (deletedUser.length === 0) {
      return NextResponse.json({ error: 'User not found' }, { status: 404 });
    }

    return NextResponse.json({ success: true, user: deletedUser[0] });
  } catch (error) {
    console.error('Error deleting user:', error);
    return NextResponse.json({ error: 'Failed to delete user' }, { status: 500 });
  }
}
