import { NextRequest, NextResponse } from 'next/server';
import { db, schema } from '@/lib/db';
import { eq, desc, inArray, and, gte, sql } from 'drizzle-orm';
import { getSession } from '@/lib/auth';
import { getPlanCapabilities } from '@/lib/plan-access';
import { isCompanyOwner, getCompanyUsers } from '@/lib/companies';

/**
 * GET /api/companies/[id]/tokens
 * Get company's token balance and usage summary
 * - Company members: totals only
 * - Company owner: totals + per-user breakdown
 */
export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id: companyId } = await params;

    // Authenticate user
    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 belongs to this company
    if (session.user.companyId !== companyId) {
      return NextResponse.json(
        { error: 'Access denied. You are not a member of this company.' },
        { status: 403 }
      );
    }

    const isOwner = await isCompanyOwner(session.user.id, companyId);

    // Get company data
    const company = await db.query.companies.findFirst({
      where: eq(schema.companies.id, companyId),
      columns: { id: true, name: true, ownedTokens: true, freeTokensConsumed: true, package: true, licenseCreditsRemaining: true },
    });

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

    // Get all company users to calculate total consumption
    const companyUsers = await getCompanyUsers(companyId);

    // Get all projects for company users and sum up tokens used (single query, no N+1)
    let totalTokensConsumed = 0;
    let totalProjects = 0;
    const userProjects: Record<string, { userId: string; userName: string; userEmail: string; projects: number; tokensUsed: number }> = {};

    const companyUserIds = companyUsers.map((u) => u.id);
    const allProjects = companyUserIds.length > 0
      ? await db.query.projects.findMany({
          where: inArray(schema.projects.userId, companyUserIds),
          columns: { id: true, name: true, userId: true, tokensUsed: true },
        })
      : [];

    const projectsByUser = new Map<string, typeof allProjects>();
    for (const p of allProjects) {
      if (!p.userId) continue;
      const bucket = projectsByUser.get(p.userId) ?? [];
      bucket.push(p);
      projectsByUser.set(p.userId, bucket);
    }
    totalTokensConsumed = allProjects.reduce((sum, p) => sum + (p.tokensUsed ?? 0), 0);
    totalProjects = allProjects.length;

    for (const user of companyUsers) {
      const projects = projectsByUser.get(user.id) ?? [];
      const userTokens = projects.reduce((sum, p) => sum + (p.tokensUsed ?? 0), 0);
      userProjects[user.id] = {
        userId: user.id,
        userName: user.name || '—',
        userEmail: user.email,
        projects: projects.length,
        tokensUsed: userTokens,
      };
    }

    // Fetch token activity logs for owner (most recent 100)
    const logs = isOwner
      ? await db.query.tokenLogs.findMany({
          where: eq(schema.tokenLogs.companyId, companyId),
          orderBy: [desc(schema.tokenLogs.createdAt)],
          limit: 100,
        })
      : [];

    // Current billing cycle: 1st of this month
    const now = new Date();
    const periodStart = new Date(now.getFullYear(), now.getMonth(), 1);
    const [cycleRow] = await db
      .select({ total: sql<number>`coalesce(sum(${schema.tokenLogs.tokensConsumed}), 0)` })
      .from(schema.tokenLogs)
      .where(and(eq(schema.tokenLogs.companyId, companyId), gte(schema.tokenLogs.createdAt, periodStart)));
    const currentCycleConsumed = Number(cycleRow?.total ?? 0);

    const includedCreditsAllowance = getPlanCapabilities(company.package).includedCreditsTokens;
    const licenseRemaining =
      typeof company.licenseCreditsRemaining === 'number'
        ? company.licenseCreditsRemaining
        : includedCreditsAllowance;

    return NextResponse.json({
      company: {
        id: company.id,
        name: company.name,
        package: company.package,
        ownedTokens: company.ownedTokens,
        freeTokensConsumed: company.freeTokensConsumed ?? 0,
        licenseCreditsRemaining: licenseRemaining,
        includedCreditsAllowance,
      },
      tokens: {
        /** Plan credits remaining for this billing period (tokens). */
        licenseCreditsRemaining: licenseRemaining,
        /** Alias for clients that read `remaining` as plan credits. */
        remaining: licenseRemaining,
        includedCreditsAllowance,
        adminBonusTokens: company.ownedTokens,
        consumed: totalTokensConsumed,
        owned: company.ownedTokens,
        /** Tokens logged in the current billing cycle (since 1st of this month). */
        currentCycleConsumed,
      },
      conversionCount: totalProjects,
      usage: isOwner ? Object.values(userProjects).sort((a, b) => b.tokensUsed - a.tokensUsed) : [],
      logs,
      allProjects: isOwner ? allProjects.map((p) => ({ id: p.id, name: p.name, userId: p.userId })) : [],
      isOwner,
    });
  } catch (error) {
    console.error('Get company tokens error:', error);
    return NextResponse.json({ error: 'Failed to fetch token data' }, { status: 500 });
  }
}
