import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { prisma } from "@/lib/db";
import { logger } from "@/lib/logger";
import { withRateLimit, rateLimiters } from "@/lib/rate-limiter";
import { z } from "zod";
import { withCSRF } from "@/lib/csrf";
import { AppointmentProvisioningService } from "@/lib/services/appointment-provisioning.service";
import { getSectorForIndustry } from "@/lib/config/industry-sector-map";

// Validation schema
const companyInfoSchema = z.object({
  companyName: z.string().min(2).max(100),
  industry: z.string().min(1),
  companySize: z.string().min(1),
  gccCountry: z.string().min(1),
  country: z.string().optional().nullable(),
  city: z.string().optional().nullable(),
  address: z.string().optional().nullable(),
  phoneNumber: z.string().optional().nullable(),
  website: z.string().optional().nullable(),
  agentCount: z.string().optional().nullable(),
  agentUseCase: z.string().optional().nullable(),
  services: z.array(z.string()).optional().nullable(),
  companyDescription: z.string().optional().nullable(),
  selectedPlan: z.string().optional().nullable(),
  billingPeriod: z.string().optional().nullable(),
  currency: z.string().optional().nullable(),
  stripeSessionId: z.string().optional().nullable(),
  email: z.string().email().optional(),
});

// Force dynamic rendering
export const dynamic = "force-dynamic";
export const runtime = "nodejs";

async function handler(req: NextRequest) {
  try {
    // Get authenticated session
    const session = await auth();
    if (!session?.user?.email) {
      // Try to get email from request body if not authenticated
      const body = await req.json();
      const userEmail = body.email;

      if (!userEmail) {
        return NextResponse.json(
          { error: "Email is required" },
          { status: 400 },
        );
      }

      // Find user by email instead of session
      const user = await prisma.users.findUnique({
        where: { email: userEmail.toLowerCase() },
      });

      if (!user) {
        logger.warn("User not found for company info update", {
          email: userEmail,
          hasBody: !!body,
        });
        return NextResponse.json(
          {
            error: "User not found. Please complete email verification first.",
            code: "USER_NOT_FOUND",
          },
          { status: 404 },
        );
      }

      logger.info("User found, updating company info", {
        userId: user.id,
        userEmail: user.email,
      });

      // Continue with user from database
      return await updateCompanyInfo(req, user.id, body);
    }

    // User is authenticated via session
    const body = await req.json();

    // 🔐 SAFETY CHECK: Ensure session.user.id exists
    if (!session.user.id) {
      logger.error("Session missing user.id", {
        hasSession: !!session,
        hasUser: !!session.user,
        userEmail: session.user?.email,
        sessionKeys: Object.keys(session || {}),
        userKeys: Object.keys(session.user || {}),
      });

      // Fallback: Try to find user by email
      const user = await prisma.users.findUnique({
        where: { email: session.user.email!.toLowerCase() },
      });

      if (!user) {
        return NextResponse.json(
          {
            error: "Session invalid - user ID missing. Please log in again.",
            code: "SESSION_INVALID",
          },
          { status: 401 },
        );
      }

      logger.warn("Recovered user ID from email lookup", {
        email: session.user.email,
        userId: user.id,
      });

      return await updateCompanyInfo(req, user.id, body);
    }

    return await updateCompanyInfo(req, session.user.id as string, body);
  } catch (error) {
    logger.error("Error in company info handler", error);
    return NextResponse.json(
      { error: "Failed to save company information" },
      { status: 500 },
    );
  }
}

async function updateCompanyInfo(
  req: NextRequest,
  userId: string,
  body: Record<string, unknown>,
) {
  try {
    // Log incoming data for debugging
    logger.info("Updating company info", {
      userId,
      hasGccCountry: !!body.gccCountry,
      hasPhoneNumber: !!body.phoneNumber,
      hasServices: !!body.services,
    });

    // Validate request body
    const validation = companyInfoSchema.safeParse(body);

    if (!validation.success) {
      logger.warn("Invalid company info data", {
        errors: validation.error.errors,
        userId,
        receivedData: body,
      });
      return NextResponse.json(
        {
          error: "Invalid data",
          details: validation.error.errors.map((e) => ({
            field: e.path.join("."),
            message: e.message,
          })),
        },
        { status: 400 },
      );
    }

    const data = validation.data;

    // Format website URL if provided
    let websiteUrl = data.website;
    if (websiteUrl && !websiteUrl.startsWith("http")) {
      websiteUrl = `https://${websiteUrl}`;
    }

    // Update user record with company information (via Convex-backed adapter)
    let updatedUser;
    try {
      logger.info("Updating user record", {
        userId,
        companyName: data.companyName,
        industry: data.industry,
      });

      updatedUser = await prisma.users.update({
        where: { id: userId },
        data: {
          companyName: data.companyName,
          industry: data.industry,
          companySize: data.companySize,
          country: data.gccCountry || data.country || null,
          city: data.city || null,
          address: data.address || data.gccCountry || null,
          phoneNumber: data.phoneNumber || null,
          website: websiteUrl || null,
          selectedPackage: data.selectedPlan || null,
          goals: data.services ? { services: data.services } : undefined,
          updatedAt: new Date(),
        },
      });

      logger.info("User updated successfully", {
        userId,
        companyName: updatedUser.companyName,
        industry: updatedUser.industry,
      });
    } catch (prismaError: unknown) {
      const pErr = prismaError as Record<string, unknown>;
      logger.error("CRITICAL: Database update failed", {
        error: pErr.message,
        code: pErr.code,
        meta: pErr.meta,
        userId,
        data,
      });
      throw new Error(`Database update failed: ${pErr.message}`);
    }

    // Log audit event
    const ip =
      req.headers.get("x-forwarded-for") ||
      req.headers.get("x-real-ip") ||
      "127.0.0.1";
    await prisma.audit_logs.create({
      data: {
        id: crypto.randomUUID(), // Generate unique ID for audit log
        userId,
        type: "company_info_update",
        action: "User updated company information",
        success: true,
        ip,
        userAgent: req.headers.get("user-agent") || undefined,
        metadata: {
          companyName: data.companyName,
          industry: data.industry,
        },
      },
    });

    logger.info("Company info updated successfully", {
      userId,
      companyName: data.companyName,
    });

    // ── Auto-provision appointment types (non-blocking) ───────────────
    if (data.industry) {
      try {
        const sector = getSectorForIndustry(data.industry);
        const provisionResult =
          await AppointmentProvisioningService.provisionCoreTypes(
            userId, // org lookup falls back to userId if no org exists yet
            data.industry,
            userId,
          );
        logger.info("Appointment types provisioned", {
          userId,
          industry: data.industry,
          sector,
          ...provisionResult,
        });
      } catch (provisionError) {
        // Never block onboarding on provisioning failure
        logger.warn("Appointment provisioning failed (non-blocking)", {
          userId,
          industry: data.industry,
          error:
            provisionError instanceof Error
              ? provisionError.message
              : String(provisionError),
        });
      }
    }

    return NextResponse.json({
      success: true,
      message: "Company information saved successfully",
    });
  } catch (error: unknown) {
    const err = error instanceof Error ? error : new Error(String(error));
    logger.error("Error updating company info", {
      error: err.message,
      stack: err.stack,
      userId,
    });

    // Return more specific error message
    const errorMessage = err.message || "Failed to save company information";
    return NextResponse.json(
      {
        error: errorMessage,
        details: process.env.NODE_ENV === "development" ? err.stack : undefined,
      },
      { status: 500 },
    );
  }
}

// Apply CSRF protection and rate limiting
export const POST = withCSRF(withRateLimit(handler, rateLimiters.authGeneral));
