// controllers/productTeamController.ts
import { Request, Response, NextFunction } from "express";
import {
  productTeamService,
  ProductTeamCreateData,
  ProductTeamUpdateData,
  ProductTeamFilters,
} from "./product.team.service";
import { catchAsyncError } from "../../middlewares/catchAsyncError";
import ErrorHandler from "../../middlewares/error";
import { AuthRequest } from "../../middlewares/auth";
import database from "../../config/db";

export const productTeamController = {
  // Add team member to product
  addTeamMember: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      const data: ProductTeamCreateData = req.body;

      // Validation
      if (!data.product_id) {
        return next(new ErrorHandler("Product ID is required", 400));
      }

      if (!data.creator_id) {
        return next(new ErrorHandler("Creator ID is required", 400));
      }

      // Validate role
      const validRoles = [
        "founder",
        "co-founder",
        "admin",
        "member",
        "contributor",
        "adviser",
      ];
      if (data.role && !validRoles.includes(data.role)) {
        return next(
          new ErrorHandler(
            `Invalid role. Must be one of: ${validRoles.join(", ")}`,
            400,
          ),
        );
      }

      // Validate commitment level
      const validCommitmentLevels = [
        "full-time",
        "part-time",
        "contractor",
        "advisor",
      ];
      if (
        data.commitment_level &&
        !validCommitmentLevels.includes(data.commitment_level)
      ) {
        return next(
          new ErrorHandler(
            `Invalid commitment level. Must be one of: ${validCommitmentLevels.join(", ")}`,
            400,
          ),
        );
      }

      try {
        const teamMember = await productTeamService.addTeamMember(data);

        // Emit socket event
        if (req.app.get("io")) {
          const io = req.app.get("io");
          io.to(`product:${data.product_id}`).emit("team:member_added", {
            team_member: teamMember,
            product_id: data.product_id,
          });

          // Notify the added user
          io.to(`user:${data.creator_id}`).emit("team:invited", {
            product_id: data.product_id,
            role: data.role,
            invited_by: userId,
          });
        }

        // Log activity
        try {
          await database.query(
            `INSERT INTO activities (
            account_id, activity_type, entity_type, entity_id, 
            details, is_public
          ) VALUES ($1, $2, $3, $4, $5, $6)`,
            [
              userId,
              "team_member_added",
              "product_team",
              teamMember.id,
              JSON.stringify({
                product_id: data.product_id,
                added_user_id: data.creator_id,
                role: data.role,
              }),
              true,
            ],
          );
        } catch (activityError) {
          console.error("Failed to log activity:", activityError);
        }

        res.status(201).json({
          success: true,
          message: "Team member added successfully",
          data: teamMember,
        });
      } catch (error: any) {
        return next(new ErrorHandler(error.message, 400));
      }
    },
  ),

  // Get team member by ID
  getTeamMemberById: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { id } = req.params;

      const teamMember = await productTeamService.getTeamMemberById(id);

      if (!teamMember) {
        return next(new ErrorHandler("Team member not found", 404));
      }

      res.status(200).json({
        success: true,
        data: teamMember,
      });
    },
  ),

  // Get all team members
  getAllTeamMembers: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const {
        page = 1,
        limit = 20,
        product_id,
        creator_id,
        role,
        department,
        is_public,
        is_active = "true",
        is_featured,
        is_verified,
        commitment_level,
        search,
        sort_by = "display_order",
        order = "asc",
      } = req.query;

      const filters: ProductTeamFilters = {
        page: parseInt(page as string),
        limit: parseInt(limit as string),
        product_id: product_id as string,
        creator_id: creator_id as string,
        role: role as string,
        department: department as string,
        is_public: is_public ? is_public === "true" : undefined,
        is_active: is_active ? is_active === "true" : true,
        is_featured: is_featured ? is_featured === "true" : undefined,
        is_verified: is_verified ? is_verified === "true" : undefined,
        commitment_level: commitment_level as string,
        search: search as string,
        sort_by: sort_by as string,
        order: order as "asc" | "desc",
      };

      const result = await productTeamService.getAllTeamMembers(filters);

      res.status(200).json({
        success: true,
        ...result,
      });
    },
  ),

  // Update team member
  updateTeamMember: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;
      const data: ProductTeamUpdateData = req.body;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      // Validate role if provided
      if (data.role) {
        const validRoles = [
          "founder",
          "co-founder",
          "admin",
          "member",
          "contributor",
          "adviser",
        ];
        if (!validRoles.includes(data.role)) {
          return next(
            new ErrorHandler(
              `Invalid role. Must be one of: ${validRoles.join(", ")}`,
              400,
            ),
          );
        }
      }

      // Validate commitment level if provided
      if (data.commitment_level) {
        const validCommitmentLevels = [
          "full-time",
          "part-time",
          "contractor",
          "advisor",
        ];
        if (!validCommitmentLevels.includes(data.commitment_level)) {
          return next(
            new ErrorHandler(
              `Invalid commitment level. Must be one of: ${validCommitmentLevels.join(", ")}`,
              400,
            ),
          );
        }
      }

      try {
        const updatedTeamMember = await productTeamService.updateTeamMember(
          id,
          data,
          userId,
        );

        // Emit socket event
        if (req.app.get("io")) {
          const io = req.app.get("io");
          io.to(`product:${updatedTeamMember.product_id}`).emit(
            "team:member_updated",
            {
              team_member: updatedTeamMember,
              product_id: updatedTeamMember.product_id,
            },
          );
        }

        res.status(200).json({
          success: true,
          message: "Team member updated successfully",
          data: updatedTeamMember,
        });
      } catch (error: any) {
        return next(
          new ErrorHandler(
            error.message,
            error.message.includes("permission") ? 403 : 400,
          ),
        );
      }
    },
  ),

  // Remove team member
  removeTeamMember: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      try {
        // Get team member info before removal
        const teamMember = await productTeamService.getTeamMemberById(id);

        const removedTeamMember = await productTeamService.removeTeamMember(
          id,
          userId,
        );

        // Emit socket event
        if (req.app.get("io")) {
          const io = req.app.get("io");
          io.to(`product:${teamMember.product_id}`).emit(
            "team:member_removed",
            {
              team_member_id: id,
              product_id: teamMember.product_id,
              removed_user_id: teamMember.creator_id,
            },
          );

          // Notify the removed user
          io.to(`user:${teamMember.creator_id}`).emit("team:removed", {
            product_id: teamMember.product_id,
          });
        }

        res.status(200).json({
          success: true,
          message: "Team member removed successfully",
          data: removedTeamMember,
        });
      } catch (error: any) {
        return next(
          new ErrorHandler(
            error.message,
            error.message.includes("permission") ? 403 : 400,
          ),
        );
      }
    },
  ),

  // Get product team summary
  getProductTeamSummary: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { productId } = req.params;

      if (!productId) {
        return next(new ErrorHandler("Product ID is required", 400));
      }

      const summary = await productTeamService.getProductTeamSummary(productId);

      res.status(200).json({
        success: true,
        data: summary,
      });
    },
  ),

  // Get user's product portfolio
  getUserProductPortfolio: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const userId = req.user?.id;
      const { userId: paramUserId } = req.params;

      const targetUserId = paramUserId || userId;

      if (!targetUserId) {
        return next(new ErrorHandler("User ID is required", 400));
      }

      const portfolio =
        await productTeamService.getUserProductPortfolio(targetUserId);

      res.status(200).json({
        success: true,
        data: portfolio,
      });
    },
  ),

  // Get team member stats
  getTeamMemberStats: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const userId = req.user?.id;
      const { userId: paramUserId } = req.params;

      const targetUserId = paramUserId || userId;

      if (!targetUserId) {
        return next(new ErrorHandler("User ID is required", 400));
      }

      const stats = await productTeamService.getTeamMemberStats(targetUserId);

      res.status(200).json({
        success: true,
        data: stats,
      });
    },
  ),

  // Check if user is in product team
  checkUserInProductTeam: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { productId } = req.params;
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      if (!productId) {
        return next(new ErrorHandler("Product ID is required", 400));
      }

      const teamMembership = await productTeamService.isUserInProductTeam(
        productId,
        userId,
      );

      res.status(200).json({
        success: true,
        data: {
          is_member: !!teamMembership,
          role: teamMembership?.role,
          is_active: teamMembership?.is_active,
        },
      });
    },
  ),

  // Get product team by role
  getTeamByRole: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { productId, role } = req.params;

      if (!productId || !role) {
        return next(new ErrorHandler("Product ID and Role are required", 400));
      }

      const team = await productTeamService.getTeamByRole(productId, role);

      res.status(200).json({
        success: true,
        data: team,
      });
    },
  ),

  // Reorder team members
  reorderTeamMembers: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { productId } = req.params;
      const userId = req.user?.id;
      const { team_member_ids } = req.body;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      if (!team_member_ids || !Array.isArray(team_member_ids)) {
        return next(new ErrorHandler("Team member IDs array is required", 400));
      }

      // Check permission
      const hasPermission =
        await productTeamService.checkProductAdminPermission(productId, userId);
      if (!hasPermission) {
        return next(
          new ErrorHandler(
            "You don't have permission to reorder team members",
            403,
          ),
        );
      }

      try {
        const updates = await productTeamService.reorderTeamMembers(
          productId,
          team_member_ids,
        );

        res.status(200).json({
          success: true,
          message: "Team members reordered successfully",
          data: updates,
        });
      } catch (error: any) {
        return next(new ErrorHandler(error.message, 400));
      }
    },
  ),

  // Search team members
  searchTeamMembers: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const {
        product_id,
        q,
        roles,
        departments,
        commitment_levels,
        limit = 10,
      } = req.query;

      const searchParams = {
        product_id: product_id as string,
        query: q as string,
        roles: roles ? (roles as string).split(",") : [],
        departments: departments ? (departments as string).split(",") : [],
        commitment_levels: commitment_levels
          ? (commitment_levels as string).split(",")
          : [],
        limit: parseInt(limit as string),
      };

      const results = await productTeamService.searchTeamMembers(searchParams);

      res.status(200).json({
        success: true,
        data: results,
      });
    },
  ),

  // Check team member permission
  checkTeamMemberPermission: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      const hasPermission = await productTeamService.checkTeamMemberPermission(
        id,
        userId,
      );

      res.status(200).json({
        success: true,
        data: {
          has_permission: hasPermission,
          team_member_id: id,
        },
      });
    },
  ),

  // Bulk add team members
  bulkAddTeamMembers: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { productId } = req.params;
      const userId = req.user?.id;
      const { members } = req.body;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      if (!members || !Array.isArray(members)) {
        return next(new ErrorHandler("Members array is required", 400));
      }

      if (members.length === 0) {
        return next(new ErrorHandler("Members array cannot be empty", 400));
      }

      try {
        const result = await productTeamService.bulkAddTeamMembers(
          productId,
          members,
          userId,
        );

        res.status(200).json({
          success: true,
          message: `Added ${result.success} team members, ${result.failed} failed`,
          data: result,
        });
      } catch (error: any) {
        return next(new ErrorHandler(error.message, 400));
      }
    },
  ),

  // Update last active time
  updateLastActive: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      const updated = await productTeamService.updateLastActive(id, userId);

      res.status(200).json({
        success: true,
        message: "Last active time updated",
        data: updated,
      });
    },
  ),

  // Get enriched team data
  getEnrichedTeamData: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { productId } = req.params;

      if (!productId) {
        return next(new ErrorHandler("Product ID is required", 400));
      }

      const teamData = await productTeamService.getEnrichedTeamData(productId);

      res.status(200).json({
        success: true,
        data: teamData,
      });
    },
  ),

  // Verify team member (admin only)
  verifyTeamMember: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;
      const { verified = true, verification_note } = req.body;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      // Check admin permission
      const teamMember = await productTeamService.getTeamMemberById(id);
      if (!teamMember) {
        return next(new ErrorHandler("Team member not found", 404));
      }

      const hasPermission =
        await productTeamService.checkProductAdminPermission(
          teamMember.product_id,
          userId,
        );
      if (!hasPermission) {
        return next(new ErrorHandler("Admin access required", 403));
      }

      const updated = await productTeamService.verifyTeamMember(
        id,
        verified,
        verification_note,
      );

      res.status(200).json({
        success: true,
        message: `Team member ${verified ? "verified" : "unverified"} successfully`,
        data: updated,
      });
    },
  ),

  // Feature team member
  featureTeamMember: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;
      const { featured = true } = req.body;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      // Check admin permission
      const teamMember = await productTeamService.getTeamMemberById(id);
      if (!teamMember) {
        return next(new ErrorHandler("Team member not found", 404));
      }

      const hasPermission =
        await productTeamService.checkProductAdminPermission(
          teamMember.product_id,
          userId,
        );
      if (!hasPermission) {
        return next(new ErrorHandler("Admin access required", 403));
      }

      const updated = await productTeamService.featureTeamMember(id, featured);

      res.status(200).json({
        success: true,
        message: `Team member ${featured ? "featured" : "unfeatured"} successfully`,
        data: updated,
      });
    },
  ),

  // Get team analytics
  getTeamAnalytics: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { productId } = req.params;

      if (!productId) {
        return next(new ErrorHandler("Product ID is required", 400));
      }

      const analytics = await productTeamService.getTeamAnalytics(productId);

      res.status(200).json({
        success: true,
        data: analytics,
      });
    },
  ),

  // Get my product teams
  getMyProductTeams: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      const filters: ProductTeamFilters = {
        creator_id: userId,
        is_active: true,
        limit: 100,
      };

      const result = await productTeamService.getAllTeamMembers(filters);

      res.status(200).json({
        success: true,
        data: result.data,
        total: result.pagination.total,
      });
    },
  ),

  // Leave product team
  leaveProductTeam: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      // Check if user is the team member
      const teamMember = await productTeamService.getTeamMemberById(id);
      if (!teamMember) {
        return next(new ErrorHandler("Team member not found", 404));
      }

      if (teamMember.creator_id !== userId) {
        return next(
          new ErrorHandler("You can only leave your own team membership", 403),
        );
      }

      // Don't allow founders to leave without transferring ownership
      if (teamMember.role === "founder") {
        return next(
          new ErrorHandler(
            "Founders cannot leave the team. Please transfer ownership first.",
            400,
          ),
        );
      }

      const leftTeam = await productTeamService.removeTeamMember(id, userId);

      res.status(200).json({
        success: true,
        message: "Successfully left the product team",
        data: leftTeam,
      });
    },
  ),
};
