import { Body, Controller, Post, HttpCode, HttpStatus, UseGuards, Get, Request, UnauthorizedException, Param, Patch, Delete, Query } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBody, ApiBearerAuth } from '@nestjs/swagger';
import { AuthService } from './auth.service';
import { RegisterDto, LoginDto, RequestOtpDto, VerifyOtpDto, RequestPasswordResetDto, ResetPasswordDto } from './auth.dto';
import { JwtGuard } from '../../common/jwt.guard';
import { RolesGuard } from '../../common/roles.guard';
import { Roles } from '../../common/roles.decorator';
import { UserRole } from '@prisma/client';

@ApiTags('Auth')
@Controller('auth')
export class AuthController {
  constructor(private service: AuthService) {}

  @Post('register')
  @ApiOperation({ 
    summary: 'Register new passenger account',
    description: 'Create a new passenger account with email, phone, and password. Returns user details and JWT token for immediate login.'
  })
  @ApiResponse({ status: 201, description: 'Account created successfully. Returns user object and JWT token.' })
  @ApiResponse({ status: 400, description: 'Validation error (invalid email, weak password, etc.)' })
  @ApiResponse({ status: 409, description: 'Email or phone already registered' })
  @ApiBody({ type: RegisterDto })
  register(@Body() dto: RegisterDto) { return this.service.register(dto); }

  @Post('login')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ 
    summary: 'Login with email and password',
    description: 'Authenticate user and receive JWT token. Token expires in 7 days by default. Failed login attempts are tracked and account may be locked after 5 consecutive failures.'
  })
  @ApiResponse({ status: 200, description: 'Login successful. Returns JWT token and user details.' })
  @ApiResponse({ status: 401, description: 'Invalid credentials or account locked' })
  @ApiResponse({ status: 403, description: 'Account temporarily blocked due to fraud detection' })
  @ApiBody({ type: LoginDto })
  login(@Body() dto: LoginDto) { return this.service.login(dto); }

  @Post('otp/request')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ 
    summary: 'Request OTP verification code',
    description: 'Send a 6-digit OTP code to user email. Code expires in 10 minutes. Used for registration verification, password reset, or two-factor authentication.'
  })
  @ApiResponse({ status: 200, description: 'OTP sent successfully to email' })
  @ApiResponse({ status: 404, description: 'Email not found (for PASSWORD_RESET purpose)' })
  @ApiResponse({ status: 429, description: 'Too many OTP requests. Please wait before requesting again.' })
  @ApiBody({ type: RequestOtpDto })
  requestOtp(@Body() dto: RequestOtpDto) { return this.service.requestOtp(dto); }

  @Post('otp/verify')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ 
    summary: 'Verify OTP code',
    description: 'Validate the 6-digit OTP code sent to user email. Code must match and not be expired.'
  })
  @ApiResponse({ status: 200, description: 'OTP verified successfully' })
  @ApiResponse({ status: 400, description: 'Invalid or expired OTP code' })
  @ApiResponse({ status: 404, description: 'No OTP found for this email and purpose' })
  @ApiBody({ type: VerifyOtpDto })
  verifyOtp(@Body() dto: VerifyOtpDto) { return this.service.verifyOtp(dto); }

  @Post('password/reset-request')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ 
    summary: 'Request password reset link',
    description: 'Send password reset link to user email. Link contains a secure token valid for 1 hour.'
  })
  @ApiResponse({ status: 200, description: 'Password reset email sent successfully' })
  @ApiResponse({ status: 404, description: 'Email not found' })
  @ApiResponse({ status: 429, description: 'Too many reset requests. Please wait before trying again.' })
  @ApiBody({ type: RequestPasswordResetDto })
  requestPasswordReset(@Body() dto: RequestPasswordResetDto) { return this.service.requestPasswordReset(dto); }

  @Post('password/reset')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ 
    summary: 'Reset password with token',
    description: 'Reset user password using the token received via email. Token is single-use and expires after 1 hour.'
  })
  @ApiResponse({ status: 200, description: 'Password reset successfully' })
  @ApiResponse({ status: 400, description: 'Invalid, expired, or already used token' })
  @ApiResponse({ status: 404, description: 'User not found' })
  @ApiBody({ type: ResetPasswordDto })
  resetPassword(@Body() dto: ResetPasswordDto) { return this.service.resetPassword(dto); }

  @Post('logout')
  @HttpCode(HttpStatus.OK)
  @UseGuards(JwtGuard)
  @ApiBearerAuth('JWT-auth')
  @ApiOperation({ 
    summary: 'Logout current user',
    description: `Logout the authenticated user and invalidate their session.

### What happens:
- Invalidates the current session token
- Records logout in audit log
- Frontend should clear stored token and redirect to home

### Authentication:
- **Required**: JWT Bearer Token
- Token will be invalidated after successful logout`
  })
  @ApiResponse({ 
    status: 200, 
    description: 'Logout successful',
    schema: {
      example: {
        success: true,
        message: 'Logged out successfully'
      }
    }
  })
  @ApiResponse({ status: 401, description: 'Unauthorized - Invalid or missing token' })
  logout(@Request() req: any) { 
    if (!req.user || !req.user.userId) {
      throw new UnauthorizedException('User not authenticated');
    }
    return this.service.logout(req.user.userId); 
  }

  @Get('profile')
  @UseGuards(JwtGuard)
  @ApiBearerAuth('JWT-auth')
  @ApiOperation({ 
    summary: 'Get current user profile',
    description: `**Returns complete user profile with all connected data**

---

### Response Includes

#### User Information
- Basic details (id, email, phone, fullName, role)
- Nationality and document information
- Fayda verification status
- Account timestamps (created, last login)

#### Passenger Data (if role=PASSENGER)
- Passenger ID and preferences
- **Loyalty Account**: Tier, points balance, lifetime points
- **Wallet Account**: Balance (minor units), currency

#### Devices
- List of registered devices with platform, name, push token, and last seen time

#### User Preferences
- Language, notification settings, etc.

---

### Use Cases

1. **App Initialization**: Fetch on app load to get user context

2. **Profile Pre-fill**: Use data to auto-fill booking forms

3. **Verification Check**: Check \`faydaVerified\` before registration

4. **Loyalty Display**: Show tier and points in UI

5. **Wallet Balance**: Display available balance

6. **Device Management**: Get list of user's registered devices

---

### Authentication
- **Required**: JWT Bearer Token
- Token must be valid and not expired
- Returns profile for authenticated user only`,
  })
  @ApiResponse({ 
    status: 200, 
    description: 'User profile retrieved successfully',
    schema: {
      example: {
        id: 'user-uuid-123',
        email: 'kelemu@email.com',
        phone: '+251911234567',
        fullName: 'Kelemu Abebe',
        role: 'PASSENGER',
        nationality: 'Ethiopian',
        nationalityCode: 'ET',
        nationalId: null,
        passportNumber: null,
        faydaVerified: true,
        faydaVerifiedAt: '2024-01-15T10:30:00.000Z',
        lastLoginAt: '2024-01-20T14:22:00.000Z',
        createdAt: '2023-12-01T08:00:00.000Z',
        passenger: {
          id: 'passenger-uuid-456',
          preferredLanguage: 'am',
          loyalty: {
            tier: 'SILVER',
            pointsBalance: 1500,
            lifetimePoints: 3000
          },
          wallet: {
            balanceMinor: 50000,
            currency: 'ETB'
          }
        },
        preferences: {
          emailNotifications: true,
          smsNotifications: true,
          language: 'am'
        },
        devices: [
          {
            id: 'device-uuid-1',
            platform: 'WEB',
            name: 'Chrome on Windows',
            pushToken: 'token-abc123',
            trusted: true,
            lastSeenAt: '2024-01-20T14:22:00.000Z'
          },
          {
            id: 'device-uuid-2',
            platform: 'IOS',
            name: 'iPhone 14',
            pushToken: 'token-xyz789',
            trusted: false,
            lastSeenAt: '2024-01-19T10:15:00.000Z'
          }
        ]
      }
    }
  })
  @ApiResponse({ 
    status: 401, 
    description: 'Unauthorized - Invalid or missing JWT token',
    schema: {
      example: {
        statusCode: 401,
        message: 'Unauthorized'
      }
    }
  })
  getProfile(@Request() req: any) { 
    console.log('Profile request - User from JWT:', req.user);
    if (!req.user || !req.user.userId) {
      throw new UnauthorizedException('User not authenticated');
    }
    return this.service.getProfile(req.user.userId); 
  }

  @Get('users')
  @UseGuards(JwtGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.SUPERVISOR)
  @ApiBearerAuth('JWT-auth')
  @ApiOperation({ summary: 'Get all backoffice users (admin/supervisor only)' })
  getUsers(
    @Query('search') search?: string,
    @Query('role') role?: string,
    @Query('status') status?: string,
    @Query('page') page?: string,
    @Query('pageSize') pageSize?: string,
  ) {
    return this.service.getUsers({
      search,
      role,
      status,
      page: page ? parseInt(page) : 1,
      pageSize: pageSize ? parseInt(pageSize) : 10,
    });
  }

  @Post('users')
  @UseGuards(JwtGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.SUPERVISOR)
  @ApiBearerAuth('JWT-auth')
  @ApiOperation({ summary: 'Create new backoffice user (admin/supervisor only)' })
  createUser(@Body() dto: any) {
    return this.service.createUser(dto);
  }

  @Patch('users/:id')
  @UseGuards(JwtGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.SUPERVISOR)
  @ApiBearerAuth('JWT-auth')
  @ApiOperation({ summary: 'Update backoffice user (admin/supervisor only)' })
  updateUser(@Param('id') id: string, @Body() dto: any) {
    return this.service.updateUser(id, dto);
  }

  @Delete('users/:id')
  @UseGuards(JwtGuard, RolesGuard)
  @Roles(UserRole.ADMIN)
  @ApiBearerAuth('JWT-auth')
  @ApiOperation({ summary: 'Delete backoffice user (admin only)' })
  deleteUser(@Param('id') id: string) {
    return this.service.deleteUser(id);
  }

  @Post('users/:id/reset-password')
  @UseGuards(JwtGuard, RolesGuard)
  @Roles(UserRole.ADMIN, UserRole.SUPERVISOR)
  @ApiBearerAuth('JWT-auth')
  @ApiOperation({ summary: 'Reset user password with temporary password (admin/supervisor only)' })
  resetUserPassword(@Param('id') id: string, @Body() dto: { tempPassword: string }) {
    return this.service.resetUserPassword(id, dto.tempPassword);
  }
}
