/**
 * WhatsApp Templates Service Tests
 *
 * Tests all 7 pure formatting functions in whatsapp-templates.service.ts.
 * These are stateless functions with ZERO dependencies -- no mocks needed.
 *
 * Each function is tested in both English and Arabic.
 */

import {
  formatViewingConfirmation,
  formatViewingReminder,
  formatPostViewingFollowUp,
  formatViewingCancellation,
  formatPriceDropAlert,
  formatStatusChangeAlert,
  formatNewMatchesNotification,
} from "@/lib/services/real-estate/whatsapp-templates.service";

// ═══════════════════════════════════════════════════════════════════════════
// 1. formatViewingConfirmation
// ═══════════════════════════════════════════════════════════════════════════

describe("formatViewingConfirmation", () => {
  const baseData = {
    clientName: "Ahmed",
    propertyTitle: "Luxury Villa in The Pearl",
    propertyAddress: "The Pearl, Doha",
    viewingDate: "2026-02-20",
    viewingTime: "10:00 AM",
    brokerName: "Sarah Johnson",
    brokerPhone: "+974 5555 1234",
    viewingType: "IN_PERSON",
    mapUrl: null,
    meetingLink: null,
  };

  describe("English", () => {
    it("should include property title, date/time, and broker details", () => {
      const result = formatViewingConfirmation(baseData, "en");

      expect(result).toContain("*Viewing Confirmed*");
      expect(result).toContain("Hi Ahmed!");
      expect(result).toContain("Luxury Villa in The Pearl");
      expect(result).toContain("The Pearl, Doha");
      expect(result).toContain("2026-02-20 at 10:00 AM");
      expect(result).toContain("Broker: Sarah Johnson");
      expect(result).toContain("+974 5555 1234");
      expect(result).toContain("Please arrive 5 minutes early");
      expect(result).toContain("_Powered by Mawidi_");
    });

    it("should include map URL when provided", () => {
      const data = { ...baseData, mapUrl: "https://maps.google.com/abc" };
      const result = formatViewingConfirmation(data, "en");

      expect(result).toContain("Map: https://maps.google.com/abc");
    });

    it("should NOT include map line when mapUrl is null", () => {
      const result = formatViewingConfirmation(baseData, "en");

      expect(result).not.toContain("Map:");
    });

    it("should include meeting link for virtual viewings", () => {
      const data = {
        ...baseData,
        viewingType: "VIRTUAL",
        meetingLink: "https://zoom.us/j/123456",
      };
      const result = formatViewingConfirmation(data, "en");

      expect(result).toContain("Meeting link: https://zoom.us/j/123456");
    });

    it("should NOT include meeting link for in-person viewings even if link present", () => {
      const data = {
        ...baseData,
        viewingType: "IN_PERSON",
        meetingLink: "https://zoom.us/j/123456",
      };
      const result = formatViewingConfirmation(data, "en");

      expect(result).not.toContain("Meeting link");
    });

    it("should NOT include meeting link for virtual viewings when link is null", () => {
      const data = {
        ...baseData,
        viewingType: "VIRTUAL",
        meetingLink: null,
      };
      const result = formatViewingConfirmation(data, "en");

      expect(result).not.toContain("Meeting link");
    });
  });

  describe("Arabic", () => {
    it("should include Arabic heading and client greeting", () => {
      const result = formatViewingConfirmation(baseData, "ar");

      expect(result).toContain(
        "*\u062A\u0623\u0643\u064A\u062F \u0627\u0644\u0645\u0639\u0627\u064A\u0646\u0629*",
      );
      expect(result).toContain("\u0645\u0631\u062D\u0628\u0627\u064B Ahmed!");
      expect(result).toContain("Luxury Villa in The Pearl");
      expect(result).toContain("The Pearl, Doha");
      expect(result).toContain("Sarah Johnson");
      expect(result).toContain("+974 5555 1234");
      expect(result).toContain(
        "_\u0628\u0648\u0627\u0633\u0637\u0629 \u0645\u0627\u0648\u062F\u064A_",
      );
    });

    it("should include meeting link for virtual viewings in Arabic", () => {
      const data = {
        ...baseData,
        viewingType: "VIRTUAL",
        meetingLink: "https://zoom.us/j/123456",
      };
      const result = formatViewingConfirmation(data, "ar");

      expect(result).toContain(
        "\u0631\u0627\u0628\u0637 \u0627\u0644\u0627\u062C\u062A\u0645\u0627\u0639",
      );
      expect(result).toContain("https://zoom.us/j/123456");
    });

    it("should include map URL in Arabic", () => {
      const data = { ...baseData, mapUrl: "https://maps.google.com/xyz" };
      const result = formatViewingConfirmation(data, "ar");

      expect(result).toContain("\u0627\u0644\u062E\u0631\u064A\u0637\u0629");
      expect(result).toContain("https://maps.google.com/xyz");
    });
  });
});

// ═══════════════════════════════════════════════════════════════════════════
// 2. formatViewingReminder
// ═══════════════════════════════════════════════════════════════════════════

describe("formatViewingReminder", () => {
  const baseData = {
    clientName: "Fatima",
    propertyTitle: "3BR Apartment in West Bay",
    propertyAddress: "West Bay, Doha",
    viewingDate: "2026-02-21",
    viewingTime: "2:00 PM",
    brokerName: "Omar Ali",
    brokerPhone: "+974 5555 5678",
    mapUrl: null,
    reminderType: "24h" as const,
  };

  describe("English - 24h reminder", () => {
    it('should say "Tomorrow" in heading and time note', () => {
      const result = formatViewingReminder(baseData, "en");

      expect(result).toContain("*Viewing Reminder - Tomorrow*");
      expect(result).toContain("Tomorrow, 2026-02-21 at 2:00 PM");
      expect(result).toContain("Don't forget your appointment!");
    });

    it("should include broker name and phone", () => {
      const result = formatViewingReminder(baseData, "en");

      expect(result).toContain("Broker: Omar Ali");
      expect(result).toContain("+974 5555 5678");
    });

    it("should include footer", () => {
      const result = formatViewingReminder(baseData, "en");
      expect(result).toContain("_Powered by Mawidi_");
    });

    it("should include map URL when provided", () => {
      const data = { ...baseData, mapUrl: "https://maps.google.com/def" };
      const result = formatViewingReminder(data, "en");

      expect(result).toContain("Map: https://maps.google.com/def");
    });
  });

  describe("English - 2h reminder", () => {
    it('should say "Today" and "in 2 Hours" heading', () => {
      const data = { ...baseData, reminderType: "2h" as const };
      const result = formatViewingReminder(data, "en");

      expect(result).toContain("*Your Viewing is in 2 Hours*");
      expect(result).toContain("Today at 2:00 PM");
      expect(result).toContain("See you soon!");
    });
  });

  describe("Arabic - 24h reminder", () => {
    it('should include Arabic heading with "Tomorrow" equivalent', () => {
      const result = formatViewingReminder(baseData, "ar");

      expect(result).toContain(
        "\u062A\u0630\u0643\u064A\u0631 \u0628\u0627\u0644\u0645\u0639\u0627\u064A\u0646\u0629 - \u063A\u062F\u0627\u064B",
      );
      expect(result).toContain("\u063A\u062F\u0627\u064B 2026-02-21");
      expect(result).toContain(
        "\u0644\u0627 \u062A\u0646\u0633 \u0645\u0648\u0639\u062F\u0643!",
      );
    });

    it("should include broker phone", () => {
      const result = formatViewingReminder(baseData, "ar");
      expect(result).toContain("+974 5555 5678");
    });
  });

  describe("Arabic - 2h reminder", () => {
    it('should say "Today" equivalent and "See you soon" in Arabic', () => {
      const data = { ...baseData, reminderType: "2h" as const };
      const result = formatViewingReminder(data, "ar");

      expect(result).toContain(
        "\u0645\u0639\u0627\u064A\u0646\u062A\u0643 \u0628\u0639\u062F \u0633\u0627\u0639\u062A\u064A\u0646",
      );
      expect(result).toContain("\u0627\u0644\u064A\u0648\u0645");
      expect(result).toContain(
        "\u0646\u0631\u0627\u0643 \u0642\u0631\u064A\u0628\u0627\u064B!",
      );
    });
  });
});

// ═══════════════════════════════════════════════════════════════════════════
// 3. formatPostViewingFollowUp
// ═══════════════════════════════════════════════════════════════════════════

describe("formatPostViewingFollowUp", () => {
  const baseData = {
    clientName: "Mohammed",
    propertyTitle: "Penthouse at Lusail",
    agencyName: "Al Jazeera Properties",
  };

  describe("English", () => {
    it("should include property name and ask about interest", () => {
      const result = formatPostViewingFollowUp(baseData, "en");

      expect(result).toContain("*Post-Viewing Follow-Up*");
      expect(result).toContain("Hi Mohammed,");
      expect(result).toContain("*Penthouse at Lusail*");
      expect(result).toContain("Schedule a second viewing");
      expect(result).toContain("Make an offer");
      expect(result).toContain("See similar properties");
      expect(result).toContain("Reply to let us know!");
      expect(result).toContain("Al Jazeera Properties");
      expect(result).toContain("_Powered by Mawidi_");
    });
  });

  describe("Arabic", () => {
    it("should include Arabic heading and property name", () => {
      const result = formatPostViewingFollowUp(baseData, "ar");

      expect(result).toContain(
        "*\u0645\u062A\u0627\u0628\u0639\u0629 \u0628\u0639\u062F \u0627\u0644\u0645\u0639\u0627\u064A\u0646\u0629*",
      );
      expect(result).toContain("\u0645\u0631\u062D\u0628\u0627\u064B Mohammed");
      expect(result).toContain("*Penthouse at Lusail*");
      expect(result).toContain(
        "\u062D\u062C\u0632 \u0645\u0639\u0627\u064A\u0646\u0629 \u062B\u0627\u0646\u064A\u0629",
      );
      expect(result).toContain(
        "\u062A\u0642\u062F\u064A\u0645 \u0639\u0631\u0636",
      );
      expect(result).toContain(
        "\u0639\u0631\u0636 \u0639\u0642\u0627\u0631\u0627\u062A \u0645\u0634\u0627\u0628\u0647\u0629",
      );
      expect(result).toContain("Al Jazeera Properties");
      expect(result).toContain(
        "_\u0628\u0648\u0627\u0633\u0637\u0629 \u0645\u0627\u0648\u062F\u064A_",
      );
    });
  });
});

// ═══════════════════════════════════════════════════════════════════════════
// 4. formatViewingCancellation
// ═══════════════════════════════════════════════════════════════════════════

describe("formatViewingCancellation", () => {
  const baseData = {
    clientName: "Khalid",
    propertyTitle: "Studio in Msheireb",
    viewingDate: "2026-03-01",
    viewingTime: "11:00 AM",
  };

  describe("English", () => {
    it("should format cancellation without reason", () => {
      const result = formatViewingCancellation(baseData, "en");

      expect(result).toContain("*Viewing Cancelled*");
      expect(result).toContain("Hi Khalid,");
      expect(result).toContain("Studio in Msheireb");
      expect(result).toContain("2026-03-01 at 11:00 AM");
      expect(result).not.toContain("Reason:");
      expect(result).toContain("If you would like to reschedule");
      expect(result).toContain("_Powered by Mawidi_");
    });

    it("should include cancellation reason when provided", () => {
      const data = { ...baseData, reason: "Property is under maintenance" };
      const result = formatViewingCancellation(data, "en");

      expect(result).toContain("Reason: Property is under maintenance");
    });
  });

  describe("Arabic", () => {
    it("should format cancellation without reason in Arabic", () => {
      const result = formatViewingCancellation(baseData, "ar");

      expect(result).toContain(
        "*\u0625\u0644\u063A\u0627\u0621 \u0627\u0644\u0645\u0639\u0627\u064A\u0646\u0629*",
      );
      expect(result).toContain("\u0645\u0631\u062D\u0628\u0627\u064B Khalid");
      expect(result).toContain("Studio in Msheireb");
      expect(result).not.toContain("\u0627\u0644\u0633\u0628\u0628:");
      expect(result).toContain(
        "_\u0628\u0648\u0627\u0633\u0637\u0629 \u0645\u0627\u0648\u062F\u064A_",
      );
    });

    it("should include cancellation reason in Arabic when provided", () => {
      const data = {
        ...baseData,
        reason:
          "\u0627\u0644\u0639\u0642\u0627\u0631 \u062A\u062D\u062A \u0627\u0644\u0635\u064A\u0627\u0646\u0629",
      };
      const result = formatViewingCancellation(data, "ar");

      expect(result).toContain(
        "\u0627\u0644\u0633\u0628\u0628: \u0627\u0644\u0639\u0642\u0627\u0631 \u062A\u062D\u062A \u0627\u0644\u0635\u064A\u0627\u0646\u0629",
      );
    });
  });
});

// ═══════════════════════════════════════════════════════════════════════════
// 5. formatPriceDropAlert
// ═══════════════════════════════════════════════════════════════════════════

describe("formatPriceDropAlert", () => {
  const baseData = {
    clientName: "Nadia",
    propertyTitle: "2BR Flat in Al Sadd",
    propertyAddress: "Al Sadd, Doha",
    oldPrice: 1000000,
    newPrice: 850000,
    currency: "QAR",
    dropPercentage: 15,
  };

  describe("English", () => {
    it("should show old price with strikethrough and new price bold", () => {
      const result = formatPriceDropAlert(baseData, "en");

      expect(result).toContain("*Price Drop Alert*");
      expect(result).toContain("Hi Nadia,");
      expect(result).toContain("2BR Flat in Al Sadd");
      expect(result).toContain("Al Sadd, Doha");
      // Old price with strikethrough
      expect(result).toMatch(/~QAR [\d,]+~/);
      // New price with bold and percentage
      expect(result).toMatch(/\*QAR [\d,]+\* \(15% off\)/);
      expect(result).toContain("Reply to schedule a viewing.");
      expect(result).toContain("_Powered by Mawidi_");
    });

    it("should round percentage to nearest integer", () => {
      const data = { ...baseData, dropPercentage: 12.7 };
      const result = formatPriceDropAlert(data, "en");

      expect(result).toContain("13% off");
    });
  });

  describe("Arabic", () => {
    it("should show old price with strikethrough and new price bold in Arabic", () => {
      const result = formatPriceDropAlert(baseData, "ar");

      expect(result).toContain(
        "*\u062A\u0646\u0628\u064A\u0647 \u0627\u0646\u062E\u0641\u0627\u0636 \u0627\u0644\u0633\u0639\u0631*",
      );
      expect(result).toContain("\u0645\u0631\u062D\u0628\u0627\u064B Nadia");
      expect(result).toContain("2BR Flat in Al Sadd");
      expect(result).toContain("Al Sadd, Doha");
      // Old price with strikethrough (AR format: amount currency)
      expect(result).toMatch(/~[\d\u0660-\u0669,٬]+ QAR~/);
      // New price bold with Arabic "drop" text
      expect(result).toMatch(/\*[\d\u0660-\u0669,٬]+ QAR\*/);
      expect(result).toContain("\u0627\u0646\u062E\u0641\u0627\u0636 15%");
      expect(result).toContain(
        "_\u0628\u0648\u0627\u0633\u0637\u0629 \u0645\u0627\u0648\u062F\u064A_",
      );
    });
  });
});

// ═══════════════════════════════════════════════════════════════════════════
// 6. formatStatusChangeAlert
// ═══════════════════════════════════════════════════════════════════════════

describe("formatStatusChangeAlert", () => {
  const baseData = {
    clientName: "Tariq",
    propertyTitle: "Compound Villa in Al Wakrah",
  };

  describe("English", () => {
    it.each([
      ["SOLD", "Sold"],
      ["RENTED", "Rented"],
      ["UNDER_OFFER", "Under Offer"],
      ["OFF_MARKET", "Off Market"],
      ["AVAILABLE", "Available"],
      ["EXPIRED", "Expired"],
    ])(
      'should map status %s to human-readable label "%s"',
      (statusEnum, label) => {
        const result = formatStatusChangeAlert(
          { ...baseData, newStatus: statusEnum },
          "en",
        );

        expect(result).toContain("*Property Status Update*");
        expect(result).toContain("Hi Tariq,");
        expect(result).toContain("Compound Villa in Al Wakrah");
        expect(result).toContain(`New status: *${label}*`);
        expect(result).toContain("Reply for more information.");
        expect(result).toContain("_Powered by Mawidi_");
      },
    );

    it("should fall back to raw status for unknown enum values", () => {
      const result = formatStatusChangeAlert(
        { ...baseData, newStatus: "PENDING_REVIEW" },
        "en",
      );

      expect(result).toContain("New status: *PENDING_REVIEW*");
    });
  });

  describe("Arabic", () => {
    it.each([
      ["SOLD", "\u0645\u064F\u0628\u0627\u0639"],
      ["RENTED", "\u0645\u0624\u062C\u0631"],
      ["UNDER_OFFER", "\u062A\u062D\u062A \u0627\u0644\u0639\u0631\u0636"],
      ["OFF_MARKET", "\u062E\u0627\u0631\u062C \u0627\u0644\u0633\u0648\u0642"],
      ["AVAILABLE", "\u0645\u062A\u0627\u062D"],
      ["EXPIRED", "\u0645\u0646\u062A\u0647\u064A"],
    ])('should map status %s to Arabic label "%s"', (statusEnum, label) => {
      const result = formatStatusChangeAlert(
        { ...baseData, newStatus: statusEnum },
        "ar",
      );

      expect(result).toContain(
        "*\u062A\u062D\u062F\u064A\u062B \u062D\u0627\u0644\u0629 \u0627\u0644\u0639\u0642\u0627\u0631*",
      );
      expect(result).toContain("\u0645\u0631\u062D\u0628\u0627\u064B Tariq");
      expect(result).toContain(`*${label}*`);
      expect(result).toContain(
        "_\u0628\u0648\u0627\u0633\u0637\u0629 \u0645\u0627\u0648\u062F\u064A_",
      );
    });

    it("should fall back to raw status for unknown enum values", () => {
      const result = formatStatusChangeAlert(
        { ...baseData, newStatus: "PENDING_REVIEW" },
        "ar",
      );

      expect(result).toContain("*PENDING_REVIEW*");
    });
  });
});

// ═══════════════════════════════════════════════════════════════════════════
// 7. formatNewMatchesNotification
// ═══════════════════════════════════════════════════════════════════════════

describe("formatNewMatchesNotification", () => {
  const makeMatch = (i: number) => ({
    title: `Property ${i}`,
    address: `District ${i}, Doha`,
    bedrooms: i + 1,
    area: 100 + i * 50,
    price: 500000 + i * 100000,
    currency: "QAR",
    referenceNumber: `REF-${String(i).padStart(3, "0")}`,
  });

  describe("English", () => {
    it("should format a single property match", () => {
      const result = formatNewMatchesNotification(
        { clientName: "Ali", matches: [makeMatch(1)] },
        "en",
      );

      expect(result).toContain("*New Matching Properties*");
      expect(result).toContain("Hi Ali,");
      expect(result).toContain("*1* properties matching");
      expect(result).toContain("*1.* Property 1 (REF-001)");
      expect(result).toContain("District 1, Doha");
      expect(result).toContain("2 BR");
      expect(result).toContain("sqm");
      expect(result).toContain("QAR");
      expect(result).not.toContain("more...");
      expect(result).toContain("Reply with a property number");
      expect(result).toContain("_Powered by Mawidi_");
    });

    it("should format 3 property matches", () => {
      const matches = [makeMatch(1), makeMatch(2), makeMatch(3)];
      const result = formatNewMatchesNotification(
        { clientName: "Ali", matches },
        "en",
      );

      expect(result).toContain("*3* properties matching");
      expect(result).toContain("*1.* Property 1");
      expect(result).toContain("*2.* Property 2");
      expect(result).toContain("*3.* Property 3");
      expect(result).not.toContain("more...");
    });

    it("should show overflow count for 7 properties (capped at 5)", () => {
      const matches = Array.from({ length: 7 }, (_, i) => makeMatch(i + 1));
      const result = formatNewMatchesNotification(
        { clientName: "Ali", matches },
        "en",
      );

      expect(result).toContain("*7* properties matching");
      expect(result).toContain("*1.* Property 1");
      expect(result).toContain("*5.* Property 5");
      expect(result).not.toContain("*6.* Property 6");
      expect(result).toContain("And *2* more...");
    });

    it("should handle properties without reference numbers", () => {
      const match = { ...makeMatch(1), referenceNumber: undefined };
      const result = formatNewMatchesNotification(
        { clientName: "Ali", matches: [match] },
        "en",
      );

      expect(result).toContain("*1.* Property 1");
      expect(result).not.toContain("(REF-");
    });

    it("should show exactly 5 properties with overflow for 6+ matches", () => {
      const matches = Array.from({ length: 6 }, (_, i) => makeMatch(i + 1));
      const result = formatNewMatchesNotification(
        { clientName: "Ali", matches },
        "en",
      );

      expect(result).toContain("*6* properties matching");
      expect(result).toContain("*5.* Property 5");
      expect(result).not.toContain("*6.*");
      expect(result).toContain("And *1* more...");
    });
  });

  describe("Arabic", () => {
    it("should format a single property match in Arabic", () => {
      const result = formatNewMatchesNotification(
        { clientName: "Ali", matches: [makeMatch(1)] },
        "ar",
      );

      expect(result).toContain(
        "*\u0639\u0642\u0627\u0631\u0627\u062A \u062C\u062F\u064A\u062F\u0629 \u0645\u0637\u0627\u0628\u0642\u0629*",
      );
      expect(result).toContain("\u0645\u0631\u062D\u0628\u0627\u064B Ali");
      expect(result).toContain("*1*");
      expect(result).toContain("*1.* Property 1 (REF-001)");
      expect(result).toContain("\u063A\u0631\u0641 \u0646\u0648\u0645");
      expect(result).toContain("\u0645\u00B2");
      expect(result).toContain(
        "_\u0628\u0648\u0627\u0633\u0637\u0629 \u0645\u0627\u0648\u062F\u064A_",
      );
    });

    it("should show overflow count in Arabic for 7 properties", () => {
      const matches = Array.from({ length: 7 }, (_, i) => makeMatch(i + 1));
      const result = formatNewMatchesNotification(
        { clientName: "Ali", matches },
        "ar",
      );

      expect(result).toContain("*7*");
      expect(result).toContain("*5.* Property 5");
      expect(result).not.toContain("*6.* Property 6");
      expect(result).toContain("*2*");
      expect(result).toContain(
        "\u0639\u0642\u0627\u0631\u0627\u062A \u0623\u062E\u0631\u0649...",
      );
    });

    it("should NOT show overflow for exactly 5 matches", () => {
      const matches = Array.from({ length: 5 }, (_, i) => makeMatch(i + 1));
      const result = formatNewMatchesNotification(
        { clientName: "Ali", matches },
        "ar",
      );

      expect(result).toContain("*5*");
      expect(result).toContain("*5.* Property 5");
      expect(result).not.toContain(
        "\u0639\u0642\u0627\u0631\u0627\u062A \u0623\u062E\u0631\u0649",
      );
    });
  });
});
