import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { PrismaService } from '../../common/prisma.service';
import { CreateTravelerProfileDto, CreateSavedRouteDto, RegisterPassengerDto } from './passengers.dto';
import { VerifaydaService } from '../verifayda/verifayda.service';

interface PassengerFilters {
  search?: string;
  verified?: boolean;
  page?: number;
  pageSize?: number;
}

@Injectable()
export class PassengersService {
  constructor(
    private prisma: PrismaService,
    private verifaydaService: VerifaydaService,
  ) {}

  async findAll(filters: PassengerFilters = {}) {
    const { search, verified, page = 1, pageSize = 20 } = filters;
    const skip = (page - 1) * pageSize;
    
    const where: any = { user: { role: 'PASSENGER' } };
    
    if (search) {
      where.user = {
        ...where.user,
        OR: [
          { fullName: { contains: search, mode: 'insensitive' } },
          { email: { contains: search, mode: 'insensitive' } },
          { phone: { contains: search, mode: 'insensitive' } },
        ],
      };
    }
    
    if (verified !== undefined) {
      where.user = {
        ...where.user,
        nationalId: verified ? { not: null } : null,
      };
    }
    
    const [items, total] = await Promise.all([
      this.prisma.passenger.findMany({
        where,
        skip,
        take: pageSize,
        orderBy: { createdAt: 'desc' },
        include: {
          user: true,
          loyalty: true,
          wallet: true,
          _count: {
            select: {
              bookings: true,
            },
          },
        },
      }),
      this.prisma.passenger.count({ where }),
    ]);
    
    return {
      items: items.map(passenger => {
        const user = passenger.user as any;
        return {
          id: passenger.id,
          userId: passenger.userId,
          fullName: user.fullName,
          email: user.email,
      phone: user.phone?.startsWith('+guest-') ? null : user.phone,
          nationalId: user.nationalId,
          nationality: user.nationality,
          dateOfBirth: user.dateOfBirth ?? null,
          gender: user.gender ?? null,
          passportNumber: user.passportNumber,
          passportCountry: user.passportCountry ?? null,
          verified: !!user.nationalId,
          loyaltyTier: passenger.loyalty?.tier || 'BRONZE',
          loyaltyPoints: passenger.loyalty?.pointsBalance || 0,
          totalBookings: passenger._count.bookings,
          createdAt: passenger.createdAt,
          updatedAt: user.updatedAt,
          loyalty: passenger.loyalty,
          wallet: passenger.wallet,
        };
      }),
      meta: {
        page,
        pageSize,
        total,
        totalPages: Math.ceil(total / pageSize),
      },
    };
  }

  async getProfile(passengerId: string) {
    const passenger = await this.prisma.passenger.findUnique({
      where: { id: passengerId },
      include: {
        user: true,
        bookings: { 
          orderBy: { createdAt: 'desc' }, 
          take: 10, 
          include: { 
            schedule: { include: { originStation: true, destinationStation: true, train: true } }, 
            seats: { include: { seat: { include: { coach: true } } } } 
          } 
        },
        loyalty: true, 
        wallet: true, 
        travelerProfiles: true, 
        savedRoutes: true,
      },
    });
    if (!passenger) throw new NotFoundException('Passenger not found');
    return {
      id: passenger.id,
      fullName: passenger.user.fullName,
      email: passenger.user.email,
      phone: passenger.user.phone,
      createdAt: passenger.createdAt,
      bookings: passenger.bookings.map((b) => ({
        id: b.id, 
        bookingRef: b.bookingRef, 
        status: b.status, 
        totalFare: b.totalMinor / 100, 
        createdAt: b.createdAt,
        trip: {
          number: b.schedule.train.number,
          origin: { 
            id: b.schedule.originStation.id, 
            name: b.schedule.originStation.name, 
            code: b.schedule.originStation.code, 
            city: b.schedule.originStation.city 
          },
          destination: { 
            id: b.schedule.destinationStation.id, 
            name: b.schedule.destinationStation.name, 
            code: b.schedule.destinationStation.code, 
            city: b.schedule.destinationStation.city 
          },
          departureAt: b.schedule.departureAt,
        },
        passengers: b.seats.map((bs) => ({ 
          fullName: bs.passengerName, 
          seat: { 
            number: bs.seat.seatNumber, 
            coach: bs.seat.coach.number, 
            class: 'N/A' 
          } 
        })),
      })),
    };
  }

  async getStats(passengerId: string) {
    const [totalTrips, totalSpendResult, loyalty] = await Promise.all([
      this.prisma.booking.count({ where: { passengerId, status: 'COMPLETED' } }),
      this.prisma.booking.aggregate({ where: { passengerId, status: 'COMPLETED' }, _sum: { totalMinor: true } }),
      this.prisma.loyaltyAccount.findUnique({ where: { passengerId } }),
    ]);
    const totalSpend = (totalSpendResult._sum.totalMinor ?? 0) / 100;
    return { totalTrips, totalSpend, loyaltyPoints: loyalty?.pointsBalance ?? 0, co2Saved: totalTrips * 6 };
  }

  async savePassengers(passengers: any[], userId?: string, deviceId?: string) {
    if (!passengers || !Array.isArray(passengers)) {
      throw new BadRequestException('Passengers array is required');
    }

    if (passengers.length === 0) {
      throw new BadRequestException('At least one passenger is required');
    }

    const savedProfiles = await Promise.all(
      passengers.map((p) =>
        this.prisma.savedPassengerProfile.create({
          data: {
            userId,
            deviceId,
            passengerName: p.name || p.passengerName,
            dateOfBirth: new Date(p.dateOfBirth),
            idDocumentType: p.nationalId ? 'NATIONAL_ID' : 'PASSPORT',
            passportNumber: p.passportNumber,
            passportCountry: p.passportCountry,
            nationality: p.nationality,
            phone: p.phone,
            email: p.email,
          },
        })
      )
    );
    return {
      count: savedProfiles.length,
      passengerIds: savedProfiles.map(p => p.id),
      passengers: savedProfiles.map(p => ({
        id: p.id,
        passengerName: p.passengerName,
        dateOfBirth: p.dateOfBirth,
        nationality: p.nationality,
      })),
      message: 'Passenger details saved successfully',
    };
  }

  createTravelerProfile(dto: CreateTravelerProfileDto) {
    return this.prisma.travelerProfile.create({ 
      data: { 
        ...dto, 
        dateOfBirth: dto.dateOfBirth ? new Date(dto.dateOfBirth) : null 
      } 
    });
  }

  getTravelerProfiles(passengerId: string) { 
    return this.prisma.travelerProfile.findMany({ where: { passengerId } }); 
  }

  createSavedRoute(dto: CreateSavedRouteDto) { 
    return this.prisma.savedRoute.create({ data: dto }); 
  }

  getSavedRoutes(passengerId: string) { 
    return this.prisma.savedRoute.findMany({ where: { passengerId }, orderBy: { tripCount: 'desc' } }); 
  }

  async updatePassenger(id: string, dto: any) {
    const passenger = await this.prisma.passenger.findUnique({ where: { id } });
    if (!passenger) throw new NotFoundException('Passenger not found');
    return this.prisma.passenger.update({
      where: { id },
      data: {
        user: {
          update: {
            fullName: dto.fullName || undefined,
            email: dto.email || undefined,
            phone: dto.phone || undefined,
            nationality: dto.nationality || undefined,
          },
        },
      },
      include: {
        user: true,
        loyalty: true,
      },
    });
  }

  async registerPassenger(dto: RegisterPassengerDto) {
    const isEthiopian = !!dto.nationalId;
    const isLoggedIn = !!dto.userId;
    let verifiedData: any = null;

    if (isEthiopian && dto.verifyWithFayda !== false) {
      try {
        const verification = await this.verifaydaService.verifyNationalId(dto.nationalId!);
        if (verification.verified && verification.passengerData) {
          verifiedData = verification.passengerData;
        }
      } catch (error) {
        console.warn('Fayda verification failed, using manual data:', error);
      }
    }

    const finalData = {
      passengerName: verifiedData?.fullName || dto.passengerName,
      dateOfBirth: verifiedData?.dateOfBirth || new Date(dto.dateOfBirth),
      nationality: verifiedData?.nationality || dto.nationality || (isEthiopian ? 'Ethiopian' : null),
      gender: verifiedData?.gender || dto.gender,
      phone: dto.phone,
      email: dto.email,
    };

    if (isLoggedIn) {
      const user = await this.prisma.user.findUnique({
        where: { id: dto.userId },
        include: { passenger: true },
      });

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

      if (!user.faydaVerified && verifiedData) {
        await this.prisma.user.update({
          where: { id: dto.userId },
          data: {
            fullName: finalData.passengerName,
            nationality: finalData.nationality,
            nationalId: dto.nationalId,
            passportNumber: dto.passportNumber,
            faydaVerified: !!verifiedData,
            faydaVerifiedAt: verifiedData ? new Date() : null,
          },
        });
      }

      return {
        id: user.passenger?.id || user.id,
        passengerName: finalData.passengerName,
        dateOfBirth: finalData.dateOfBirth,
        nationality: finalData.nationality,
        verified: !!verifiedData,
        linked: true,
        message: 'Passenger details saved and linked to user account',
      };
    }

    const profile = await this.prisma.savedPassengerProfile.create({
      data: {
        deviceId: dto.deviceId,
        passengerName: finalData.passengerName,
        dateOfBirth: finalData.dateOfBirth,
        idDocumentType: isEthiopian ? 'NATIONAL_ID' : 'PASSPORT',
        passportNumber: dto.passportNumber,
        passportCountry: dto.passportCountry,
        nationality: finalData.nationality,
        phone: dto.phone,
        email: dto.email,
      },
    });

    return {
      id: profile.id,
      passengerName: finalData.passengerName,
      dateOfBirth: finalData.dateOfBirth,
      nationality: finalData.nationality,
      verified: !!verifiedData,
      linked: false,
      message: 'Passenger details saved for guest booking',
    };
  }

  async deletePassenger(id: string) {
    const passenger = await this.prisma.passenger.findUnique({ where: { id } });
    if (!passenger) throw new NotFoundException('Passenger not found');
    return this.prisma.passenger.delete({ where: { id } });
  }

  async checkPassengerUsage(id: string) {
    const [bookingCount, loyaltyAccount, walletAccount] = await Promise.all([
      this.prisma.booking.count({ where: { passengerId: id } }),
      this.prisma.loyaltyAccount.findUnique({ where: { passengerId: id } }),
      this.prisma.walletAccount.findUnique({ where: { passengerId: id } }),
    ]);

    const usage = [];
    if (bookingCount > 0) usage.push(`${bookingCount} booking(s)`);
    if (loyaltyAccount) usage.push('Loyalty account');
    if (walletAccount) usage.push('Wallet account');

    return {
      isInUse: usage.length > 0,
      affectedModules: usage,
    };
  }
}
