import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from '../../entities/user.entity';
import { License } from '../../entities/license.entity';
import { TeamMember } from '../../entities/team-member.entity';
import { Role } from '../../entities/role.entity';

export interface JwtPayload {
  sub: string;
  email: string;
  username: string;
  is_super_admin: boolean;
  license_id?: string;
  permissions?: Record<string, any>;
}

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private configService: ConfigService,
    @InjectRepository(User)
    private userRepository: Repository<User>,
    @InjectRepository(License)
    private licenseRepository: Repository<License>,
    @InjectRepository(TeamMember)
    private teamMemberRepository: Repository<TeamMember>,
    @InjectRepository(Role)
    private roleRepository: Repository<Role>,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: configService.get<string>('jwt.secret'),
    });
  }

  async validate(payload: JwtPayload): Promise<JwtPayload> {
    const user = await this.userRepository.findOne({
      where: { id: payload.sub },
    });

    if (!user) {
      throw new UnauthorizedException('User not found');
    }

    // Update last_login_at
    await this.userRepository.update(user.id, {
      last_login_at: new Date(),
    });

    // Find user's license - either as owner or team member
    let license: License | null = null;
    let role: Role | null = null;

    // Check if user owns a license
    license = await this.licenseRepository.findOne({
      where: { owner_user_id: user.id },
    });

    if (license) {
      // Owner has full permissions - find Owner role
      role = await this.roleRepository.findOne({
        where: { role_name: 'Owner', is_system_default: true },
      });
    } else if (!user.is_super_admin) {
      // Check if user is a team member (skip for super admins without a license)
      const teamMember = await this.teamMemberRepository.findOne({
        where: { user_id: user.id },
        relations: ['license', 'role'],
      });

      if (teamMember && teamMember.accepted_at) {
        license = teamMember.license;
        role = teamMember.role;
      }
    }

    return {
      sub: user.id,
      email: user.email,
      username: user.username,
      is_super_admin: user.is_super_admin,
      license_id: license?.id,
      permissions: role?.permissions || {},
    };
  }
}
