import { Response } from "express";
import { Types } from "mongoose";
import SubscriptionPlanModel from "../../models/SubscriptionPlanModel";
import UserSubscriptionModel from "../../models/UserSubscriptionModel";
import ResponseUtil from "../../utils/Response/responseUtils";
import { STATUS_CODES } from "../../constants/statusCodes";
import { CustomRequest } from "../../interfaces/auth";
import { subscriptionPlanBodySchema } from "../../validators/adminValidators";

async function ensureDefaultPlans() {
  const count = await SubscriptionPlanModel.countDocuments();
  if (count > 0) return;
  await SubscriptionPlanModel.insertMany([
    {
      name: "Basic",
      slug: "basic",
      description: "Core trip planning",
      priceCents: 0,
      currency: "usd",
      interval: "month",
      features: ["Trip planner", "Gas station map"],
      isActive: true,
    },
    {
      name: "Pro",
      slug: "pro",
      description: "Advanced insights",
      priceCents: 999,
      currency: "usd",
      interval: "month",
      features: ["Everything in Basic", "Fuel analytics"],
      isActive: true,
    },
  ]);
}

export const listPlansAdmin = async (req: CustomRequest, res: Response) => {
  try {
    await ensureDefaultPlans();
    const plans = await SubscriptionPlanModel.find()
      .sort({ priceCents: 1 })
      .lean();
    return ResponseUtil.successResponse(
      res,
      STATUS_CODES.SUCCESS,
      { plans },
      "Subscription plans"
    );
  } catch (e) {
    ResponseUtil.handleError(res, e);
  }
};

export const createPlanAdmin = async (req: CustomRequest, res: Response) => {
  try {
    const body = await subscriptionPlanBodySchema.parseAsync(req.body);
    const plan = await SubscriptionPlanModel.create({
      name: body.name,
      slug: body.slug,
      description: body.description ?? "",
      priceCents: body.priceCents,
      currency: body.currency ?? "usd",
      interval: body.interval,
      features: body.features ?? [],
      isActive: body.isActive ?? true,
    });
    return ResponseUtil.successResponse(
      res,
      STATUS_CODES.SUCCESS,
      { plan },
      "Plan created"
    );
  } catch (e) {
    ResponseUtil.handleError(res, e);
  }
};

export const listPurchasesAdmin = async (req: CustomRequest, res: Response) => {
  try {
    const page = Math.max(parseInt((req.query.page as string) || "1", 10), 1);
    const limit = Math.min(
      Math.max(parseInt((req.query.limit as string) || "20", 10), 1),
      100
    );
    const skip = (page - 1) * limit;
    const status = req.query.status as string | undefined;
    const filter: Record<string, unknown> = {};
    if (status) filter.status = status;

    const [subs, total] = await Promise.all([
      UserSubscriptionModel.find(filter)
        .sort({ purchasedAt: -1 })
        .skip(skip)
        .limit(limit)
        .populate("userId", "email fullName")
        .populate("planId", "name slug priceCents interval")
        .lean(),
      UserSubscriptionModel.countDocuments(filter),
    ]);

    return ResponseUtil.successResponse(
      res,
      STATUS_CODES.SUCCESS,
      {
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
        subscriptions: subs,
      },
      "Purchased subscriptions"
    );
  } catch (e) {
    ResponseUtil.handleError(res, e);
  }
};

export const recordPurchaseAdmin = async (
  req: CustomRequest,
  res: Response
) => {
  try {
    const { userId, planId, status, stripeSubscriptionId, expiresAt } =
      req.body as Record<string, string>;
    if (!userId || !planId || !Types.ObjectId.isValid(userId) || !Types.ObjectId.isValid(planId)) {
      return ResponseUtil.errorResponse(
        res,
        STATUS_CODES.BAD_REQUEST,
        "userId and planId required"
      );
    }
    const sub = await UserSubscriptionModel.create({
      userId,
      planId,
      status: status || "active",
      stripeSubscriptionId,
      expiresAt: expiresAt ? new Date(expiresAt) : undefined,
    });
    const populated = await UserSubscriptionModel.findById(sub._id)
      .populate("planId")
      .populate("userId", "email")
      .lean();
    return ResponseUtil.successResponse(
      res,
      STATUS_CODES.SUCCESS,
      { subscription: populated },
      "Subscription recorded"
    );
  } catch (e) {
    ResponseUtil.handleError(res, e);
  }
};
