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

/**
 * POST /api/admin/companies/[id]/owner
 * Create an owner for a company (admin only)
 * - Creates the user and assigns them as the company owner
 * - Only one owner per company
 */
export async function POST(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id: companyId } = 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 });
    }

    // Verify company exists
    const company = await db.query.companies.findFirst({
      where: eq(schema.companies.id, companyId),
    });

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

    // Check if company already has an owner (that is not 'pending')
    if (company.ownerId && company.ownerId !== 'pending') {
      const existingOwner = await db.query.users.findFirst({
        where: eq(schema.users.id, company.ownerId),
      });
      if (existingOwner) {
        return NextResponse.json(
          { error: 'Company already has an owner. Transfer ownership instead.' },
          { status: 400 }
        );
      }
    }

    const body = await request.json();
    const existingOwnerSchema = z.object({
      existingUserId: z.string().min(1, 'existingUserId is required'),
    });
    const existingOwnerParsed = existingOwnerSchema.safeParse(body);

    if (existingOwnerParsed.success) {
      const { existingUserId } = existingOwnerParsed.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 && existingUser.companyId && existingUser.companyId !== companyId) {
        return NextResponse.json(
          { error: 'This user is already owner of another company' },
          { status: 400 }
        );
      }

      if (existingUser.companyId && existingUser.companyId !== companyId) {
        return NextResponse.json(
          { error: 'Selected user already belongs to another company' },
          { status: 400 }
        );
      }

      // When assigning an unassigned user, ensure target company has room.
      if (!existingUser.companyId) {
        const canAdd = await canAddUserToCompany(companyId);
        if (!canAdd.allowed) {
          return NextResponse.json({ error: canAdd.reason }, { status: 400 });
        }
      }

      await db
        .update(schema.users)
        .set({
          companyId,
          isOwner: true,
          updatedAt: new Date(),
        })
        .where(eq(schema.users.id, existingUser.id));

      await db
        .update(schema.companies)
        .set({ ownerId: existingUser.id, updatedAt: new Date() })
        .where(eq(schema.companies.id, companyId));

      return NextResponse.json({
        success: true,
        user: {
          id: existingUser.id,
          email: existingUser.email,
          name: existingUser.name,
          companyId,
          isOwner: true,
        },
        message: 'Existing user assigned as company owner',
      });
    }

    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 } = 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 in another company, reject
      if (existingUser.companyId && existingUser.companyId !== companyId) {
        return NextResponse.json(
          { error: 'A user with this email already exists in another company' },
          { status: 400 }
        );
      }
      // If user exists in this company but is not owner, update them to owner
      if (existingUser.companyId === companyId) {
        // Check if company already has an owner
        const currentOwnerCheck = await db.query.users.findFirst({
          where: and(
            eq(schema.users.companyId, companyId),
            eq(schema.users.isOwner, true)
          ),
        });
        if (currentOwnerCheck && currentOwnerCheck.id !== existingUser.id) {
          return NextResponse.json(
            { error: 'Company already has a different owner. Transfer ownership instead.' },
            { status: 400 }
          );
        }

        // Update user to be owner
        await db
          .update(schema.users)
          .set({ isOwner: true, updatedAt: new Date() })
          .where(eq(schema.users.id, existingUser.id));

        // Update company ownerId
        await db
          .update(schema.companies)
          .set({ ownerId: existingUser.id, updatedAt: new Date() })
          .where(eq(schema.companies.id, companyId));

        return NextResponse.json({
          success: true,
          user: {
            id: existingUser.id,
            email: existingUser.email,
            name: existingUser.name,
            companyId,
            isOwner: true,
          },
          message: 'Existing user promoted to company owner',
        });
      }
    }

    // Check if we can add a user to this company
    const canAdd = await canAddUserToCompany(companyId);
    if (!canAdd.allowed) {
      return NextResponse.json({ error: canAdd.reason }, { status: 400 });
    }

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

    // Create owner user
    const userId = crypto.randomUUID();
    const [newUser] = await db.insert(schema.users).values({
      id: userId,
      email,
      name: name || email.split('@')[0],
      companyId,
      isOwner: true, // This is the owner
      role: 'client', // Owners are regular clients with owner privileges
      emailVerified: true,
    }).returning();

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

    // Update company with ownerId
    await db
      .update(schema.companies)
      .set({ ownerId: userId, updatedAt: new Date() })
      .where(eq(schema.companies.id, companyId));

    return NextResponse.json({
      success: true,
      user: {
        id: newUser.id,
        email: newUser.email,
        name: newUser.name,
        companyId,
        isOwner: true,
      },
      message: 'Owner created successfully. They can now login and manage the company.',
    }, { status: 201 });

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

/**
 * PUT /api/admin/companies/[id]/owner
 * Transfer ownership to another user (admin only)
 */
export async function PUT(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id: companyId } = 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 { newOwnerId } = body;

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

    // Verify company exists
    const company = await db.query.companies.findFirst({
      where: eq(schema.companies.id, companyId),
    });

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

    // Verify new owner exists and belongs to this company
    const newOwner = await db.query.users.findFirst({
      where: and(
        eq(schema.users.id, newOwnerId),
        eq(schema.users.companyId, companyId)
      ),
    });

    if (!newOwner) {
      return NextResponse.json(
        { error: 'New owner must be an existing user in this company' },
        { status: 400 }
      );
    }

    // Get current owner
    const currentOwnerId = company.ownerId;

    // Update current owner
    if (currentOwnerId && currentOwnerId !== 'pending') {
      await db
        .update(schema.users)
        .set({ isOwner: false, updatedAt: new Date() })
        .where(eq(schema.users.id, currentOwnerId));
    }

    // Update new owner
    await db
      .update(schema.users)
      .set({ isOwner: true, updatedAt: new Date() })
      .where(eq(schema.users.id, newOwnerId));

    // Update company
    await db
      .update(schema.companies)
      .set({ ownerId: newOwnerId, updatedAt: new Date() })
      .where(eq(schema.companies.id, companyId));

    return NextResponse.json({
      success: true,
      message: 'Ownership transferred successfully',
      newOwnerId,
    });

  } catch (error) {
    console.error('Error transferring ownership:', error);
    return NextResponse.json({ error: 'Failed to transfer ownership' }, { status: 500 });
  }
}
