import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Trip, TripDocument } from '../trips/schemas/trip.schema';
import { Punch, PunchDocument } from '../punches/schemas/punch.schema';
import { User, UserDocument } from '../users/schemas/user.schema';

@Injectable()
export class ExportsService {
  constructor(
    @InjectModel(Trip.name) private readonly tripModel: Model<TripDocument>,
    @InjectModel(Punch.name) private readonly punchModel: Model<PunchDocument>,
    @InjectModel(User.name) private readonly userModel: Model<UserDocument>,
  ) {}

  async exportTripsJson(filters: { from?: string; to?: string; userId?: string }) {
    const query: Record<string, unknown> = {};
    if (filters.userId) query.userId = filters.userId;
    if (filters.from || filters.to) {
      query.createdAt = {
        ...(filters.from ? { $gte: new Date(filters.from) } : {}),
        ...(filters.to ? { $lte: new Date(filters.to) } : {}),
      };
    }

    const trips = await this.tripModel.find(query).sort({ createdAt: -1 }).lean().exec();
    return Promise.all(
      trips.map(async (t) => {
        const user = await this.userModel
          .findById(t.userId)
          .select('uid fullName employeeCode')
          .lean()
          .exec();
        const punches = await this.punchModel
          .find({ tripId: t._id.toString() })
          .lean()
          .exec();
        return { ...t, id: t._id.toString(), user, punches };
      }),
    );
  }

  async exportTripsExcel(filters: { from?: string; to?: string; userId?: string }) {
    const ExcelJS = await import('exceljs');
    const trips = await this.exportTripsJson(filters);
    const workbook = new ExcelJS.Workbook();
    const sheet = workbook.addWorksheet('Trips');
    sheet.columns = [
      { header: 'Trip ID', key: 'tripId', width: 36 },
      { header: 'Employee', key: 'employee', width: 24 },
      { header: 'Status', key: 'status', width: 16 },
      { header: 'From', key: 'fromLocation', width: 24 },
      { header: 'To', key: 'toLocation', width: 24 },
      { header: 'Distance (m)', key: 'totalDistance', width: 14 },
      { header: 'Travel (s)', key: 'travelDuration', width: 12 },
      { header: 'Meeting (s)', key: 'meetingDuration', width: 12 },
      { header: 'Idle (s)', key: 'idleTime', width: 12 },
      { header: 'Productivity', key: 'productivityScore', width: 14 },
      { header: 'Created', key: 'createdAt', width: 22 },
    ];

    for (const t of trips) {
      sheet.addRow({
        tripId: t.tripId,
        employee: t.user?.fullName,
        status: t.status,
        fromLocation: t.fromLocation,
        toLocation: t.toLocation,
        totalDistance: t.totalDistance,
        travelDuration: t.travelDuration,
        meetingDuration: t.meetingDuration,
        idleTime: t.idleTime,
        productivityScore: t.productivityScore,
        createdAt: (t as { createdAt?: Date }).createdAt,
      });
    }

    return workbook.xlsx.writeBuffer();
  }

  async streamTripsPdf(
    res: import('express').Response,
    filters: { from?: string; to?: string; userId?: string },
  ) {
    const PDFDocument = (await import('pdfkit')).default;
    const trips = await this.exportTripsJson(filters);
    const doc = new PDFDocument({ margin: 40 });
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Content-Disposition', 'attachment; filename=trips-report.pdf');
    doc.pipe(res);
    doc.fontSize(18).text('Trip Track — Trips Report', { underline: true });
    doc.moveDown();
    doc.fontSize(10);
    for (const t of trips) {
      doc.text(
        `${t.tripId} | ${t.user?.fullName} | ${t.status} | ${t.totalDistance.toFixed(0)}m`,
      );
    }
    doc.end();
  }
}
