import { Injectable, NotFoundException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PrismaService } from '../../common/prisma/prisma.service';

// =============================================================================
// WhatsApp Service
// Builds the prefilled message body from the city's stored template, fills the
// variables from a vihar + its allocated volunteers, and returns both the raw
// message and the wa.me URL the frontend can open.
// =============================================================================

@Injectable()
export class WhatsappService {
  constructor(
    private readonly prisma: PrismaService,
    private readonly config: ConfigService,
  ) {}

  async buildMessageForVihar(
    cityId: number,
    viharId: number,
  ): Promise<{ message: string; waUrl: string; deepLink: string }> {
    const vihar = await this.prisma.vihar.findUnique({
      where: { viharId },
      include: {
        departureLocation: true,
        arrivalLocation: true,
        samuday: true,
        city: true,
        allocations: {
          where: { isActive: true },
          include: { user: { select: { fullName: true, phone: true } } },
        },
      },
    });
    if (!vihar || vihar.cityId !== cityId) throw new NotFoundException('Vihar not found');

    const template = await this.prisma.messageTemplate.findUnique({
      where: { cityId_templateKey: { cityId, templateKey: 'whatsapp_share' } },
    });
    if (!template) throw new NotFoundException('WhatsApp template not configured');

    const siteUrl = this.config.get<string>('NEXT_PUBLIC_SITE_URL') ?? 'http://localhost:3001';
    const deepLink = `${siteUrl}/v/${vihar.viharId}`;

    const distanceKm =
      vihar.actualDistanceKm !== null
        ? Number(vihar.actualDistanceKm).toFixed(1)
        : vihar.plannedDistanceMeters
          ? (vihar.plannedDistanceMeters / 1000).toFixed(1)
          : '?';

    const volunteersList = vihar.allocations.length
      ? vihar.allocations.map((a) => `• ${a.user.fullName}`).join('\n')
      : '(none yet)';

    const volunteerPhonesList = vihar.allocations.length
      ? vihar.allocations.map((a) => `• ${a.user.fullName} — ${a.user.phone}`).join('\n')
      : '(none yet)';

    const honorific = vihar.headSaintHonorific?.trim() ?? '';
    const headSaintFull = honorific ? `${honorific} ${vihar.headSaintName}` : vihar.headSaintName;

    const vars: Record<string, string> = {
      date: this.formatDate(vihar.viharDate),
      day: this.formatDay(vihar.viharDate),
      time: this.formatTime(vihar.plannedStartTime),
      head_saint: headSaintFull,
      head_saint_honorific: honorific,
      head_saint_name: vihar.headSaintName,
      samuday: vihar.samuday?.name ?? '—',
      sadhuji: String(vihar.sadhujiCount),
      sadhviji: String(vihar.sadhvijiCount),
      other: String(vihar.otherCount),
      from_name: vihar.departureLocation.name,
      from_address: vihar.departureLocation.formattedAddress ?? '',
      to_name: vihar.arrivalLocation.name,
      to_address: vihar.arrivalLocation.formattedAddress ?? '',
      distance_km: distanceKm,
      temple_darshan: vihar.templeDarshan ? 'Yes' : 'No',
      updhi: vihar.updhi ? 'Yes' : 'No',
      updhi_text: vihar.updhi ? '*Updhi G.Floor Per Lavi Ne Mukvi*\n🎒 *UPDHI CHE* 🎒' : '',
      volunteers: volunteersList,
      volunteer_phones: volunteerPhonesList,
      remarks: vihar.remarks ?? '—',
      deep_link: deepLink,
      city_name: vihar.city.name,
    };

    const message = template.body.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);

    const waUrl = `https://wa.me/?text=${encodeURIComponent(message)}`;
    return { message, waUrl, deepLink };
  }

  private formatDate(d: Date): string {
    // "26-4-26"  (DD-M-YY)
    const ist = new Date(d.toLocaleString('en-US', { timeZone: 'Asia/Kolkata' }));
    const dd = ist.getDate();
    const mm = ist.getMonth() + 1;
    const yy = String(ist.getFullYear()).slice(-2);
    return `${dd}-${mm}-${yy}`;
  }

  private formatDay(d: Date): string {
    return d.toLocaleDateString('en-IN', { weekday: 'long', timeZone: 'Asia/Kolkata' });
  }

  private formatTime(hhmmss: string): string {
    // "05:30:00" -> "5:30 AM"
    const [h, m] = hhmmss.split(':').map((x) => parseInt(x!, 10));
    if (h === undefined || m === undefined) return hhmmss;
    const period = h >= 12 ? 'PM' : 'AM';
    const h12 = h % 12 === 0 ? 12 : h % 12;
    return `${h12}:${m.toString().padStart(2, '0')} ${period}`;
  }
}
