import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { ConfigService } from '@nestjs/config';
import { PrismaService } from '../../../database/prisma.service';
import { ShopStatus, UserRole } from '@prisma/client';

export type JwtPayload = {
  sub: string;
  email: string | null;
  role: UserRole;
  shopId: string | null;
  ver: number;
};

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private readonly config: ConfigService,
    private readonly prisma: PrismaService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: config.get<string>('jwt.secret') ?? 'dev-jwt-secret',
    });
  }

  async validate(payload: JwtPayload) {
    const user = await this.prisma.user.findUnique({
      where: { id: payload.sub },
      select: {
        id: true,
        name: true,
        email: true,
        role: true,
        phone: true,
        referralCode: true,
        shopId: true,
        isActive: true,
        deactivatedAt: true,
        permissions: true,
        tokenVersion: true,
        adminSubscription: {
          select: {
            planExpiresAt: true,
            scheduledPlanCode: true,
            scheduledPlanAt: true,
            plan: {
              select: {
                id: true,
                code: true,
                name: true,
                priceMonthly: true,
                currency: true,
                features: true,
              },
            },
          },
        },
        shop: {
          select: {
            id: true,
            name: true,
            address: true,
            city: true,
            state: true,
            pincode: true,
            gstNo: true,
            upiId: true,
            status: true,
            approvedAt: true,
            rejectedAt: true,
            rejectedReason: true,
            isActive: true,
            deactivatedAt: true,
            walletBalance: true,
            admin: {
              select: {
                adminSubscription: {
                  select: {
                    planExpiresAt: true,
                    scheduledPlanCode: true,
                    scheduledPlanAt: true,
                    plan: {
                      select: {
                        id: true,
                        code: true,
                        name: true,
                        priceMonthly: true,
                        currency: true,
                        features: true,
                      },
                    },
                  },
                },
              },
            },
          },
        },
      },
    });
    if (!user) throw new UnauthorizedException('Invalid token');
    if (payload.ver !== user.tokenVersion)
      throw new UnauthorizedException('Token has been revoked');

    // Inactive users cannot use tokens (all roles).
    if (!user.isActive) {
      throw new UnauthorizedException('User is inactive');
    }

    // Enforce *inactive* shop state for dashboard roles on every request.
    // Pending approval is allowed (user stays logged in), but UI should gate access.
    if (user.role === UserRole.ADMIN || user.role === UserRole.SUBADMIN) {
      if (!user.shopId || !user.shop) {
        throw new UnauthorizedException('Invalid token');
      }
      // NOTE: Rejected shops are set inactive in DB, but owner must still be able
      // to log in to view rejection reason and resubmit after fixing details.
      if (!user.shop.isActive && user.shop.status !== ShopStatus.REJECTED) {
        throw new UnauthorizedException('Shop is inactive');
      }
    }
    const subscription =
      user.adminSubscription ?? user.shop?.admin?.adminSubscription ?? null;
    return {
      ...user,
      adminSubscription: undefined,
      subscription,
      shop: user.shop
        ? {
            ...user.shop,
            admin: undefined,
            plan: subscription?.plan ?? null,
            planExpiresAt: subscription?.planExpiresAt ?? null,
            scheduledPlanCode: subscription?.scheduledPlanCode ?? null,
            scheduledPlanAt: subscription?.scheduledPlanAt ?? null,
          }
        : user.shop,
    };
  }
}
