/**
 * User Profile API
 * GET - Fetch user profile information
 * PUT - Update user profile
 *
 * For team members (non-owners), company data is loaded from the organization owner's profile.
 * Team members can only edit their name and phone number.
 *
 * All data access goes through Convex. No Prisma fallback.
 */

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { convexQuery, convexMutation } from "@/lib/convex-client";
import { validateCSRFToken } from "@/lib/csrf";
import { applyRateLimit, rateLimiters } from "@/lib/rate-limiter";
import validator from "validator";
import { validatePhoneNumber } from "@/lib/validators/phone-validator";
import { getIPFromRequest, getLocationFromIP } from "@/lib/geolocation";
import { getAuthenticatedEmail } from "@/lib/utils/auth-helpers.util";
import type { Id } from "@/convex/_generated/dataModel";
import type {
  ConvexUser,
  ConvexOrganizationMembership,
  ConvexOrganization,
} from "@/lib/types/convex-entities";

/**
 * GET /api/user/profile
 * Returns current user's profile information
 */
export async function GET(request: NextRequest) {
  try {
    const userEmail = await getAuthenticatedEmail(request, auth);

    if (!userEmail) {
      return NextResponse.json(
        { success: false, error: "Unauthorized" },
        { status: 401 },
      );
    }

    // Fetch user from Convex
    const convexUser = await convexQuery<ConvexUser>(
      "auth/queries:getUserByEmail",
      { email: userEmail.toLowerCase() },
    );

    if (!convexUser) {
      return NextResponse.json(
        { success: false, error: "User not found" },
        { status: 404 },
      );
    }

    const userId =
      convexUser.prismaId || convexUser.appUserId || convexUser._id;

    // Normalize Convex user to profile shape
    const user = {
      id: userId,
      email: convexUser.email,
      name: convexUser.name || "",
      phoneNumber: convexUser.phoneNumber || null,
      avatar: convexUser.avatar || null,
      companyName: convexUser.companyName || null,
      companySize: convexUser.companySize || null,
      industry: convexUser.industry || null,
      website: convexUser.website || null,
      country: convexUser.country || null,
      city: convexUser.city || null,
      role: convexUser.role || null,
      createdAt: convexUser.createdAt
        ? new Date(convexUser.createdAt)
        : new Date(),
      emailVerified: convexUser.emailVerified
        ? new Date(convexUser.emailVerified)
        : null,
      onboardingComplete: convexUser.onboardingComplete || false,
      whatsappConnected: convexUser.whatsappConnected || false,
      whatsappNumber: convexUser.whatsappNumber || null,
      hasPassword: !!convexUser.password,
    };

    // Check organization role to determine if user is owner or team member
    let organizationRole: { role: string; organizationId: string } | null =
      null;
    let ownerCompanyData: Record<string, unknown> | null = null;
    let isTeamMember = false;

    try {
      const orgState = await convexQuery<Record<string, unknown>>(
        "organizations/queries:getOrganizationStateByUserId",
        { userId },
      );

      if (orgState) {
        const userRole = orgState.userRole as string | undefined;
        const organization = orgState.organization as
          | Record<string, unknown>
          | undefined;

        if (organization && userRole) {
          organizationRole = {
            role: userRole,
            organizationId:
              (organization._id as string) || (organization.id as string),
          };

          if (userRole !== "OWNER") {
            isTeamMember = true;

            // Fetch org owner's profile for company data
            const ownerId = organization.ownerId as string;
            if (ownerId) {
              // Look up owner's user data - try by getting org owner email first
              const ownerUser = await convexQuery<ConvexUser>(
                "auth/queries:getUserByClerkId",
                { clerkId: ownerId },
              );
              if (ownerUser) {
                ownerCompanyData = {
                  companyName: ownerUser.companyName || null,
                  companySize: ownerUser.companySize || null,
                  industry: ownerUser.industry || null,
                  website: ownerUser.website || null,
                  country: ownerUser.country || null,
                  city: ownerUser.city || null,
                };
              }
            }
          }
        }
      }
    } catch (err) {
      // Organization feature may not be fully enabled, continue without it
      console.warn("[API] Could not check organization role:", err);
    }

    // For team members, use owner's company data instead of their own
    const profileData =
      isTeamMember && ownerCompanyData
        ? {
            // User's own data (editable)
            id: user.id,
            email: user.email,
            name: user.name,
            phoneNumber: user.phoneNumber,
            avatar: user.avatar,
            role: user.role,
            createdAt: user.createdAt,
            emailVerified: user.emailVerified,
            onboardingComplete: user.onboardingComplete,
            whatsappConnected: user.whatsappConnected,
            whatsappNumber: user.whatsappNumber,
            hasPassword: user.hasPassword,
            // Company data from owner (read-only for team members)
            companyName: ownerCompanyData.companyName as string | null,
            companySize: ownerCompanyData.companySize as string | null,
            industry: ownerCompanyData.industry as string | null,
            website: ownerCompanyData.website as string | null,
            country: ownerCompanyData.country as string | null,
            city: ownerCompanyData.city as string | null,
          }
        : {
            id: user.id,
            email: user.email,
            name: user.name,
            phoneNumber: user.phoneNumber,
            avatar: user.avatar,
            companyName: user.companyName,
            companySize: user.companySize,
            industry: user.industry,
            website: user.website,
            country: user.country,
            city: user.city,
            role: user.role,
            createdAt: user.createdAt,
            emailVerified: user.emailVerified,
            onboardingComplete: user.onboardingComplete,
            whatsappConnected: user.whatsappConnected,
            whatsappNumber: user.whatsappNumber,
            hasPassword: user.hasPassword,
          };

    return NextResponse.json({
      success: true,
      user: profileData,
      organization: organizationRole
        ? {
            role: organizationRole.role,
            organizationId: organizationRole.organizationId,
            isTeamMember,
          }
        : null,
    });
  } catch (error) {
    console.error("[API] Failed to fetch profile:", error);
    return NextResponse.json(
      { success: false, error: "Internal server error" },
      { status: 500 },
    );
  }
}

/**
 * PUT /api/user/profile
 * Updates user profile information via Convex
 */
export async function PUT(request: NextRequest) {
  try {
    const userEmail = await getAuthenticatedEmail(request, auth);

    if (!userEmail) {
      return NextResponse.json(
        { success: false, error: "Unauthorized" },
        { status: 401 },
      );
    }

    // Development: Bypass rate limiting for easier testing
    const isDevelopment = process.env.NODE_ENV === "development";

    if (!isDevelopment) {
      const rateLimitResponse = await applyRateLimit(
        request,
        rateLimiters.authGeneral,
      );
      if (rateLimitResponse) return rateLimitResponse;
    }

    // CSRF protection
    const isValidCSRF = validateCSRFToken(request);
    if (!isValidCSRF) {
      return NextResponse.json(
        { success: false, error: "Invalid CSRF token" },
        { status: 403 },
      );
    }

    // Parse request body
    const body = await request.json();
    const {
      name,
      email,
      phoneNumber,
      companyName,
      companySize,
      industry,
      country,
      city,
    } = body;
    let { website } = body;

    // Normalize website URL - add https:// if no protocol provided
    if (website && website.trim() && !website.match(/^https?:\/\//i)) {
      website = "https://" + website.trim();
    }

    // Normalize phone number
    let normalizedPhone = phoneNumber;
    if (phoneNumber && phoneNumber.trim()) {
      normalizedPhone = phoneNumber.trim();
    }

    // Validation
    const errors: string[] = [];

    if (name && (name.length < 2 || name.length > 100)) {
      errors.push("Name must be between 2 and 100 characters");
    }

    if (email && !validator.isEmail(email)) {
      errors.push("Invalid email format");
    }

    if (normalizedPhone) {
      const phoneValidation = validatePhoneNumber(normalizedPhone);
      if (!phoneValidation.isValid) {
        errors.push(phoneValidation.error || "Invalid phone number format");
      }
    }

    if (
      website &&
      website.trim() &&
      !validator.isURL(website, { require_protocol: true })
    ) {
      errors.push("Invalid website URL format");
    }

    if (errors.length > 0) {
      return NextResponse.json(
        { success: false, error: errors.join(", "), errors },
        { status: 400 },
      );
    }

    // Get current user from Convex
    const currentUser = await convexQuery<ConvexUser>(
      "auth/queries:getUserByEmail",
      { email: userEmail.toLowerCase() },
    );

    if (!currentUser) {
      return NextResponse.json(
        { success: false, error: "User not found" },
        { status: 404 },
      );
    }

    // Email changes are not allowed (security policy)
    if (email && email !== currentUser.email) {
      return NextResponse.json(
        {
          success: false,
          error:
            "Email address cannot be changed. Please contact support for assistance.",
        },
        { status: 400 },
      );
    }

    const userId =
      currentUser.prismaId || currentUser.appUserId || currentUser._id;

    // Check if user is a team member - they can only update name and phone
    let isTeamMember = false;
    try {
      const orgState = await convexQuery<Record<string, unknown>>(
        "organizations/queries:getOrganizationStateByUserId",
        { userId },
      );
      if (orgState) {
        const userRole = orgState.userRole as string | undefined;
        if (userRole && userRole !== "OWNER") {
          isTeamMember = true;
        }
      }
    } catch (err) {
      // Organization feature may not be fully enabled, continue without restrictions
      console.warn("[API] Could not check organization role for update:", err);
    }

    // Build update data (only include provided fields, excluding email)
    const updateData: Record<string, unknown> = {};
    if (name !== undefined) updateData.name = name;
    if (phoneNumber !== undefined) updateData.phoneNumber = phoneNumber;

    // Team members cannot update company fields
    if (!isTeamMember) {
      if (companyName !== undefined) updateData.companyName = companyName;
      if (companySize !== undefined) updateData.companySize = companySize;
      if (industry !== undefined) updateData.industry = industry;
      if (website !== undefined) updateData.website = website;
      if (country !== undefined) updateData.country = country;
      if (city !== undefined) updateData.city = city;
    }

    // Update in Convex
    const updatedUser = await convexMutation<ConvexUser>(
      "auth/mutations:updateUser",
      {
        id: currentUser._id,
        ...updateData,
      },
    );

    // Audit log (best-effort via Convex)
    const ipAddress = await getIPFromRequest(request);
    const locationData = await getLocationFromIP(ipAddress);

    await convexMutation("auth/mutations:createAuditLog", {
      userId: currentUser._id,
      type: "account",
      action: "profile_updated",
      success: true,
      ip: ipAddress,
      userAgent: request.headers.get("user-agent") || "",
      metadata: {
        updatedFields: Object.keys(updateData),
        location: locationData,
      },
    }).catch(() => {
      /* audit log is non-fatal */
    });

    // Fetch the updated user to return
    const freshUser = await convexQuery<ConvexUser>(
      "auth/queries:getUserByEmail",
      { email: userEmail.toLowerCase() },
    );

    const responseUser = freshUser
      ? {
          id: freshUser.prismaId || freshUser.appUserId || freshUser._id,
          email: freshUser.email,
          name: freshUser.name || "",
          phoneNumber: freshUser.phoneNumber || null,
          avatar: freshUser.avatar || null,
          companyName: freshUser.companyName || null,
          companySize: freshUser.companySize || null,
          industry: freshUser.industry || null,
          website: freshUser.website || null,
          country: freshUser.country || null,
          city: freshUser.city || null,
          role: freshUser.role || null,
        }
      : {
          id: userId,
          email: userEmail,
          ...updateData,
        };

    return NextResponse.json({
      success: true,
      user: responseUser,
    });
  } catch (error) {
    console.error("[API] Failed to update profile:", error);
    return NextResponse.json(
      { success: false, error: "Failed to update profile" },
      { status: 500 },
    );
  }
}
