import { Injectable, ConflictException, UnauthorizedException } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { RegisterDto } from './dto/register.dto';
import { LoginDto } from './dto/login.dto';
import { ChangePasswordDto } from './dto/change-password.dto';
import { JwtService } from '@nestjs/jwt';
import * as bcrypt from 'bcrypt';
import { EncryptionService } from '../../common/services/encryption.service';

@Injectable()
export class AuthService {
  constructor(
    private readonly prisma: PrismaService,
    private readonly jwtService: JwtService,
    private readonly encryptionService: EncryptionService,
  ) {}

  async register(dto: RegisterDto) {
    const existing = await this.prisma.business.findUnique({
      where: { contactEmail: dto.email.toLowerCase() },
    });

    if (existing) {
      throw new ConflictException('A business with this email already exists.');
    }

    const passwordHash = await bcrypt.hash(dto.password, 10);
    const chosenPlan = (dto.selectedPlan || 'STARTER').toUpperCase();

    const business = await this.prisma.business.create({
      data: {
        name: dto.businessName,
        contactEmail: dto.email.toLowerCase(),
        contactPhone: dto.phone,
        passwordHash,
        subscriptionStatus: 'UNSUBSCRIBED',
        subscriptionPlan: chosenPlan,
        selectedPlan: chosenPlan,
        onboardingStep: 'BILLING_PENDING',
        trialStart: null,
        trialEnd: null,
      },
    });

    const payload = { sub: business.id, email: business.contactEmail };
    return {
      accessToken: this.jwtService.sign(payload),
      business: {
        id: business.id,
        name: business.name,
        email: business.contactEmail,
        phone: business.contactPhone,
        walletAddress: business.walletAddress,
        status: business.status,
        subscriptionStatus: business.subscriptionStatus,
        subscriptionPlan: business.subscriptionPlan,
        onboardingStep: business.onboardingStep,
        selectedPlan: business.selectedPlan,
        trialEnd: business.trialEnd,
      },
    };
  }

  async login(dto: LoginDto) {
    const input = dto.email.trim();
    const business = await this.prisma.business.findFirst({
      where: {
        OR: [
          { contactEmail: input.toLowerCase() },
          { contactPhone: input },
        ],
      },
    });

    if (!business) {
      throw new UnauthorizedException('Invalid email, phone number, or password.');
    }

    const isMatch = await bcrypt.compare(dto.password, business.passwordHash);
    if (!isMatch) {
      throw new UnauthorizedException('Invalid email or password.');
    }

    const payload = { sub: business.id, email: business.contactEmail };
    return {
      accessToken: this.jwtService.sign(payload),
      business: {
        id: business.id,
        name: business.name,
        email: business.contactEmail,
        phone: business.contactPhone,
        walletAddress: business.walletAddress,
        status: business.status,
        subscriptionStatus: business.subscriptionStatus,
        subscriptionPlan: business.subscriptionPlan,
        onboardingStep: business.onboardingStep,
        selectedPlan: business.selectedPlan,
        trialEnd: business.trialEnd,
      },
    };
  }

  async validateBusiness(id: string) {
    const business = await this.prisma.business.findUnique({
      where: { id },
      select: {
        id: true,
        name: true,
        contactEmail: true,
        contactPhone: true,
        walletAddress: true,
        status: true,
        subscriptionStatus: true,
        subscriptionPlan: true,
        onboardingStep: true,
        selectedPlan: true,
        trialEnd: true,
        latitude: true,
        longitude: true,
        createdAt: true,
      },
    });

    if (!business) return null;

    return {
      id: business.id,
      name: business.name,
      email: business.contactEmail,
      phone: business.contactPhone,
      walletAddress: business.walletAddress,
      status: business.status,
      subscriptionStatus: business.subscriptionStatus,
      subscriptionPlan: business.subscriptionPlan,
      onboardingStep: business.onboardingStep,
      selectedPlan: business.selectedPlan,
      trialEnd: business.trialEnd,
      latitude: business.latitude,
      longitude: business.longitude,
      createdAt: business.createdAt,
    };
  }

  async updateProfile(id: string, dto: { name: string; contactPhone?: string; walletAddress?: string; latitude?: number; longitude?: number }) {
    const business = await this.prisma.business.update({
      where: { id },
      data: {
        name: dto.name,
        contactPhone: dto.contactPhone || null,
        walletAddress: dto.walletAddress || null,
        latitude: dto.latitude !== undefined ? dto.latitude : undefined,
        longitude: dto.longitude !== undefined ? dto.longitude : undefined,
      },
      select: {
        id: true,
        name: true,
        contactEmail: true,
        contactPhone: true,
        walletAddress: true,
        latitude: true,
        longitude: true,
      },
    });

    return {
      success: true,
      business: {
        id: business.id,
        name: business.name,
        email: business.contactEmail,
        phone: business.contactPhone,
        walletAddress: business.walletAddress,
        latitude: business.latitude,
        longitude: business.longitude,
      },
    };
  }

  async changePassword(id: string, dto: ChangePasswordDto) {
    const business = await this.prisma.business.findUnique({
      where: { id },
    });

    if (!business) {
      throw new UnauthorizedException('Business profile not found.');
    }

    const isMatch = await bcrypt.compare(dto.oldPassword, business.passwordHash);
    if (!isMatch) {
      throw new UnauthorizedException('Current password does not match.');
    }

    const passwordHash = await bcrypt.hash(dto.newPassword, 10);
    await this.prisma.business.update({
      where: { id },
      data: { passwordHash },
    });

    return { success: true, message: 'Password updated successfully' };
  }
}

